├── user ├── user_config.h ├── string.h ├── mystuff.h ├── mystuff.c ├── esp_rawsend.h ├── custom_commands.c ├── esp_rawsend.c ├── customnmi.S └── user_main.c ├── web ├── md5.c ├── md5.h ├── Makefile ├── mfsmaker.c ├── pushtodev.c ├── execute_reflash.c └── page │ ├── jquery-2.1.4.min.js.gz │ ├── page.old │ ├── jquery-2.1.4.min.js.gz │ ├── index.html │ ├── main.js │ └── menuinterface.js │ ├── index.html │ ├── main.js │ └── menuinterface.js ├── custom_libpp └── libpp.a ├── .gitmodules ├── toprecorder ├── Makefile ├── toprecorder.c ├── notes.txt └── process.cpp ├── Makefile ├── user.cfg ├── LICENSE ├── README.md ├── custom_ld.ld └── notes.txt /user/user_config.h: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /user/string.h: -------------------------------------------------------------------------------- 1 | //Nothing here. 2 | -------------------------------------------------------------------------------- /web/md5.c: -------------------------------------------------------------------------------- 1 | ../esp82xx/web/md5.c -------------------------------------------------------------------------------- /web/md5.h: -------------------------------------------------------------------------------- 1 | ../esp82xx/web/md5.h -------------------------------------------------------------------------------- /web/Makefile: -------------------------------------------------------------------------------- 1 | ../esp82xx/web/Makefile -------------------------------------------------------------------------------- /web/mfsmaker.c: -------------------------------------------------------------------------------- 1 | ../esp82xx/web/mfsmaker.c -------------------------------------------------------------------------------- /web/pushtodev.c: -------------------------------------------------------------------------------- 1 | ../esp82xx/web/pushtodev.c -------------------------------------------------------------------------------- /web/execute_reflash.c: -------------------------------------------------------------------------------- 1 | ../esp82xx/web/execute_reflash.c -------------------------------------------------------------------------------- /custom_libpp/libpp.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnlohr/esp8266rawpackets/HEAD/custom_libpp/libpp.a -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "esp82xx"] 2 | path = esp82xx 3 | url = http://github.com/cnlohr/esp82xx.git 4 | -------------------------------------------------------------------------------- /web/page/jquery-2.1.4.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnlohr/esp8266rawpackets/HEAD/web/page/jquery-2.1.4.min.js.gz -------------------------------------------------------------------------------- /web/page/page.old/jquery-2.1.4.min.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnlohr/esp8266rawpackets/HEAD/web/page/page.old/jquery-2.1.4.min.js.gz -------------------------------------------------------------------------------- /toprecorder/Makefile: -------------------------------------------------------------------------------- 1 | all : toprecorder process 2 | 3 | toprecorder : toprecorder.c 4 | gcc -o $@ $^ 5 | 6 | process : process.cpp 7 | g++ -o $@ $^ -O0 -g 8 | 9 | clean : 10 | rm -rf *.o *~ toprecorder process 11 | 12 | -------------------------------------------------------------------------------- /user/mystuff.h: -------------------------------------------------------------------------------- 1 | #ifndef _MYSTUFF_H 2 | #define _MYSTUFF_H 3 | 4 | extern char generic_print_buffer[384]; 5 | 6 | #define printf( ... ) os_sprintf( generic_print_buffer, __VA_ARGS__ ); uart0_sendStr( generic_print_buffer ); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /user/mystuff.c: -------------------------------------------------------------------------------- 1 | #include "mystuff.h" 2 | 3 | char generic_print_buffer[384]; 4 | 5 | 6 | void user_rf_pre_init(void) 7 | { 8 | //nothing. 9 | } 10 | 11 | 12 | char * strcat( char * dest, char * src ) 13 | { 14 | return strcat(dest, src ); 15 | } 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include user.cfg 2 | -include esp82xx/common.mf 3 | -include esp82xx/main.mf 4 | 5 | 6 | CFLAGS += 7 | SRCS += user/esp_rawsend.c user/customnmi.S 8 | 9 | % : 10 | $(warning This is the empty rule. Something went wrong.) 11 | @true 12 | 13 | ifndef TARGET 14 | $(info Modules were not checked out... use git clone --recursive in the future. Pulling now.) 15 | $(shell git submodule update --init --recursive) 16 | endif 17 | 18 | # Example for a custom rule. 19 | # Most of the build is handled in main.mf 20 | .PHONY : showvars 21 | showvars: 22 | $(foreach v, $(.VARIABLES), $(info $(v) = $($(v)))) 23 | true 24 | 25 | -------------------------------------------------------------------------------- /user.cfg: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # User Options 3 | ############################################################################### 4 | 5 | CHIP = 8266 6 | IP = 192.168.4.1 # does not actually set the IP in firmware 7 | PORT = /dev/ttyUSB0 # could also be /dev/ttyACM0 8 | WEB_PORT = 80 9 | COM_PORT = 7777 10 | BACKEND_PORT = 7878 11 | PAGE_OFFSET = 65536 # 1048576 12 | 13 | SDK = $(HOME)/esp8266/ESP8266_NONOS_SDK 14 | #SDK_DEFAULT = $(HOME)/esp8266/esp-open-sdk 15 | ESP_GCC_VERS = 4.8.5 16 | LINKERSCRIPT ?= custom_ld.ld 17 | CUSTOMPP = 1 18 | LDFLAGS_POST = custom_libpp/libpp.a 19 | FWBURNFLAGS = -b 2000000 20 | 21 | 22 | OPTS += -DICACHE_FLASH 23 | #OPTS += -DVERIFY_FLASH_WRITE 24 | #OPTS += -DDEBUG 25 | #OPTS += -DNET_MAXTRIES=10 26 | #OPTS += -DNET_TIMEOUT=3.0 27 | #OPTS += -DFREQ=12500 28 | 29 | PAGE_TITLE = esp82xx-basic 30 | PAGE_SCRIPTS = $(wildcard page/*.js) # include all javascrpts in ./web/page/ 31 | PAGE_HEADING = Welcome to the basic Web-GUI 32 | PAGE_INFO = This is the basic web interface for esp82xx-series chips 33 | 34 | -------------------------------------------------------------------------------- /user/esp_rawsend.h: -------------------------------------------------------------------------------- 1 | #ifndef _ESP_RAWSEND_H 2 | #define _ESP_RAWSEND_H 3 | #include "c_types.h" 4 | 5 | 6 | 7 | //from https://github.com/ernacktob/esp8266_wifi_raw 8 | 9 | 10 | struct RxControl { 11 | signed rssi:8; 12 | unsigned rate:4; 13 | unsigned is_group:1; 14 | unsigned:1; 15 | unsigned sig_mode:2; 16 | unsigned legacy_length:12; 17 | unsigned damatch0:1; 18 | unsigned damatch1:1; 19 | unsigned bssidmatch0:1; 20 | unsigned bssidmatch1:1; 21 | unsigned MCS:7; 22 | unsigned CWB:1; 23 | unsigned HT_length:16; 24 | unsigned Smoothing:1; 25 | unsigned Not_Sounding:1; 26 | unsigned:1; 27 | unsigned Aggregation:1; 28 | unsigned STBC:2; 29 | unsigned FEC_CODING:1; 30 | unsigned SGI:1; 31 | unsigned rxend_state:8; 32 | unsigned ampdu_cnt:8; 33 | unsigned channel:4; 34 | unsigned:12; 35 | }; 36 | 37 | struct RxPacket { 38 | struct RxControl rx_ctl; 39 | uint8 data[]; 40 | }; 41 | 42 | typedef void (*wifi_raw_recv_cb_fn)(struct RxPacket *, void ** v); 43 | void ICACHE_FLASH_ATTR wifi_set_raw_recv_cb(wifi_raw_recv_cb_fn rx_fn); 44 | 45 | //My stuff here. 46 | //Don't use this stuff. 47 | void SetupRawsend(); 48 | int CanRawsend(); 49 | void RawSendBuffer( uint8_t * buffer, int length ); 50 | 51 | #endif 52 | 53 | 54 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Portions of this code are under various Espressif licenses. 2 | 3 | Please take not of the individual files. All files that are 4 | written without license, by me are under the MIT license as reads below. 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2014 Charles Lohr 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | -------------------------------------------------------------------------------- /user/custom_commands.c: -------------------------------------------------------------------------------- 1 | //Copyright 2015 <>< Charles Lohr, see LICENSE file. 2 | 3 | #include 4 | #include 5 | extern uint32_t debugccount; 6 | extern uint32_t debugccount2; 7 | 8 | int ICACHE_FLASH_ATTR CustomCommand(char * buffer, int retsize, char *pusrdata, unsigned short len) 9 | { 10 | char * buffend = buffer; 11 | 12 | switch( pusrdata[1] ) { 13 | case 'C': case 'c': { //Custom command test 14 | buffend += ets_sprintf( buffend, "CC" ); 15 | return buffend-buffer; 16 | } break; 17 | 18 | case 'R': case 'r': { 19 | ParamCaptureAndAdvanceInt( ); 20 | uint32_t address = ParamCaptureAndAdvanceInt( ); 21 | if( address == 0 ) 22 | { 23 | buffend += ets_sprintf( buffend, "!CR" ); 24 | } 25 | else 26 | { 27 | buffend += ets_sprintf( buffend, "CR\t%u", *(((uint32_t*)address)) ); 28 | } 29 | return buffend-buffer; 30 | } 31 | case 'W': case 'w': { 32 | ParamCaptureAndAdvanceInt( ); 33 | uint32_t address = ParamCaptureAndAdvanceInt( ); 34 | uint32_t value = ParamCaptureAndAdvanceInt( ); 35 | 36 | if( address == 0 ) 37 | { 38 | buffend += ets_sprintf( buffend, "!CW" ); 39 | } 40 | else 41 | { 42 | (*((volatile uint32_t*)address)) = value; 43 | buffend += ets_sprintf( buffend, "Cw" ); 44 | } 45 | return buffend-buffer; 46 | } 47 | case 'd': case 'D': { 48 | buffend += ets_sprintf( buffend, "CD\t%d\t%d", debugccount, debugccount2 ); 49 | return buffend-buffer; 50 | } 51 | } 52 | return -1; 53 | } 54 | -------------------------------------------------------------------------------- /toprecorder/toprecorder.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define PORT 9999 //The port on which to listen for incoming data 9 | 10 | void die(char *s) 11 | { 12 | perror(s); 13 | exit(1); 14 | } 15 | 16 | int main(void) 17 | { 18 | struct sockaddr_in si_me, si_other; 19 | 20 | int s, i, slen = sizeof(si_other) , recv_len; 21 | 22 | //create a UDP socket 23 | if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) 24 | { 25 | die("socket"); 26 | } 27 | 28 | // zero out the structure 29 | memset((char *) &si_me, 0, sizeof(si_me)); 30 | 31 | si_me.sin_family = AF_INET; 32 | si_me.sin_port = htons(PORT); 33 | si_me.sin_addr.s_addr = htonl(INADDR_ANY); 34 | 35 | //bind socket to port 36 | if( bind(s , (struct sockaddr*)&si_me, sizeof(si_me) ) == -1) 37 | { 38 | die("bind"); 39 | } 40 | 41 | while(1) 42 | { 43 | uint8_t buf[1024]; 44 | //try to receive some data, this is a blocking call 45 | if ((recv_len = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *) &si_other, &slen)) == -1) 46 | { 47 | die("recvfrom()"); 48 | } 49 | 50 | int ipl = 0; 51 | while( ipl < recv_len ) 52 | { 53 | uint8_t * bptr = &buf[ipl]; 54 | ipl += 40; 55 | 56 | //printf( "%d ", recv_len ); 57 | printf("%d.%d.%d.%d ", 58 | (si_other.sin_addr.s_addr&0xFF), 59 | ((si_other.sin_addr.s_addr&0xFF00)>>8), 60 | ((si_other.sin_addr.s_addr&0xFF0000)>>16), 61 | ((si_other.sin_addr.s_addr&0xFF000000)>>24)); 62 | 63 | int i, j, p = 0; 64 | for( j = 0; j < 3; j++ ) 65 | { 66 | for( i = 0; i < 6; i++ ) 67 | { 68 | printf( "%02x", bptr[p++] ); 69 | } 70 | printf(" "); 71 | } 72 | for( i = 0; i < 6; i++ ) 73 | { 74 | printf( "%c", bptr[p++] ); 75 | } 76 | uint32_t id = ntohl( *((uint32_t*)&bptr[p]) ); p+=4; 77 | uint32_t time = ( *((uint32_t*)&bptr[p]) ); p+=4; 78 | printf( " %u %u\n", id, time ); 79 | } 80 | } 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /toprecorder/notes.txt: -------------------------------------------------------------------------------- 1 | 147 -- 168 in -- 179 2 | | 3 | | 4 | 162 in 5 | | 6 | | 7 | 169 ------------ 241 8 | ^^^ 9 | or 167 10 | 11 | Data1: Using all the basic stuff, transmitting at CCK (1mbit/s) 12 | Data2: Same, except 54mbit/s 13 | Data3: Total overhaul on interrupt system, using interrupt's CCOUNT (DON'T USE, uS) 14 | Data4: Using Data3's overhaul, but using 0x3ff210fc instead of CCOUNT (DON'T USE, uS) 15 | 16 | Data6: Going back to CCOUNT, since 0x3ff210fc was in us. 17 | Data7: Lots of ccountdata 18 | Data8: Add 5th node in middle. 19 | 20 | Data9: Same, 54MBit/s, all nodes in staight line. 15.5' between nodes, 31' total end to end. |167 - 147 - 179| 21 | 22 | 23 | 24 | Columns in data files are: 25 | 26 | IP ADDRESS STATUS WORD XMIT MAC RX MAC CODE PID CCLOCK at receiver (in 1/160Mths of a second) 27 | 192.168.11.241 2e1c32400000 5ccf7fc0d218 5ccf7fc06055 ESPEED 106547 3757796600 28 | 192.168.11.241 1f1c32400000 5ccf7fc10b08 5ccf7fc06055 ESPEED 102321 3758311648 29 | 192.168.11.241 2b1c32400000 5ccf7fc0c75c 5ccf7fc06055 ESPEED 106097 3759192468 30 | 192.168.11.147 2c1c32400000 5ccf7fc06055 5ccf7fc0c75c ESPEED 105571 2852887099 31 | 32 | CODE is always "ESPEED" or "ESPTXX" if transmitter. Note transmitter is not necessarily actual transmit time. 33 | 34 | 35 | Status word is as follows: 36 | signed rssi:8; 37 | unsigned rate:4; 38 | unsigned is_group:1; 39 | unsigned:1; 40 | unsigned sig_mode:2; 41 | unsigned legacy_length:12; 42 | unsigned damatch0:1; 43 | unsigned damatch1:1; 44 | unsigned bssidmatch0:1; 45 | unsigned bssidmatch1:1; 46 | unsigned MCS:7; 47 | unsigned CWB:1; 48 | unsigned HT_length:16; 49 | unsigned Smoothing:1; 50 | unsigned Not_Sounding:1; 51 | unsigned:1; 52 | 53 | 54 | 214 55 | 10' 56 | === 57 | 241 ------- 25' -------- 147 58 | -- 59 | 25' 60 | -- 61 | 179 -------- 25' 169 62 | 63 | 64 | 65 | Data10: 66 | Data11: both data10 and 11 are on my front lawn, use Brendan's device configuration map. Now including transmit time. (54G) 67 | Data12: Everything same, except now 802.11G/6 68 | Data13: Everything same, except now 802.11B/11 69 | Data14: Everything same, except now 802.11N/13MBit/s 70 | Data15: Everything same, except now 802.11N/65Mbit/s 71 | Data16: Everything same, except now 802.11N/72.2Mbit/s 72 | Data17: Everything same, except now 802.11B/5.5 73 | 74 | -------------------------------------------------------------------------------- /web/page/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{PAGE_TITLE}} 5 | 6 | 7 | 8 | {{PAGE_SCRIPT}} 9 | 10 | 19 | 20 | 21 |

{{PAGE_HEADING}}

22 |
23 | 24 | 25 | 26 | 27 | 28 | 34 | 35 | 36 | 37 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |

Copyright (C) 2015-2016 <>< Charles Lohr, See LICENSE file for more info.

57 |

{{VERSSTR}}

58 |

github-logo{{PROJECT_NAME}}

59 |
60 |
...
61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /web/page/page.old/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{PAGE_TITLE}} 5 | 6 | 7 | 8 | {{PAGE_SCRIPT}} 9 | 10 | 19 | 20 | 21 |

{{PAGE_HEADING}}

22 |
23 | 24 | 25 | 26 | 27 | 28 | 34 | 35 | 36 | 37 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |

Copyright (C) 2015-2016 <>< Charles Lohr, See LICENSE file for more info.

57 |

{{VERSSTR}}

58 |

github-logo{{PROJECT_NAME}}

59 |
60 |
...
61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /user/esp_rawsend.c: -------------------------------------------------------------------------------- 1 | #include "esp_rawsend.h" 2 | #include 3 | 4 | //From https://github.com/ernacktob/esp8266_wifi_raw 5 | extern void ICACHE_FLASH_ATTR ppEnqueueRxq(void *); 6 | wifi_raw_recv_cb_fn wifi_mcb; 7 | void ICACHE_FLASH_ATTR wifi_set_raw_recv_cb(wifi_raw_recv_cb_fn rx_fn) 8 | { 9 | wifi_mcb = rx_fn; 10 | } 11 | 12 | void aaEnqueueRxq(void * v) 13 | { 14 | if (wifi_mcb) 15 | wifi_mcb((struct RxPacket *)( ((void **)v)[4]), v ); 16 | ppEnqueueRxq(v); 17 | } 18 | 19 | //I use a less evasive mechanism to send than the other packet thing. 20 | 21 | //We need to get our hands on this pointer, but I don't know it's absolute location 22 | //So, we wait for a TX packet callback and steal it from there. 23 | static void * pxpkt = 0; //This is the pointer to the structure that let's us raw send. 24 | 25 | static void txcb(uint8_t *buf, uint16 reason) 26 | { 27 | pxpkt = buf; 28 | return; 29 | #ifdef DO_DEEP_TX_DEBUG 30 | return; 31 | char ct[16]; 32 | int i = 0; 33 | ets_sprintf( ct, "<%p %d --> NODE:%p\n", buf, reason, eagle_lwip_getif(1) ); 34 | uart0_sendStr( ct ); 35 | for( i = 0; i <100; i++ ) 36 | { 37 | ets_sprintf( ct, "%02x ", buf[i] ); 38 | uart0_sendStr( ct ); 39 | } 40 | uart0_sendStr( "\n" ); 41 | 42 | uint8_t * innerbuf = ((uint32_t*)buf)[1]; 43 | ets_sprintf( ct, "\nInner [1]: %p\n", innerbuf ); 44 | uart0_sendStr( ct ); 45 | 46 | for( i = 0; i <100; i++ ) 47 | { 48 | ets_sprintf( ct, "%02x ", innerbuf[i] ); 49 | uart0_sendStr( ct ); 50 | } 51 | 52 | innerbuf = ((uint32_t*)buf)[4]; 53 | ets_sprintf( ct, "\nInner [4]: %p\n", innerbuf ); 54 | uart0_sendStr( ct ); 55 | for( i = 0; i <100; i++ ) 56 | { 57 | ets_sprintf( ct, "%02x ", innerbuf[i] ); 58 | uart0_sendStr( ct ); 59 | } 60 | 61 | 62 | innerbuf = ((uint32_t*)buf)[8]; 63 | ets_sprintf( ct, "\nInner [8]: %p\n", innerbuf ); //nothing else here... 64 | uart0_sendStr( ct ); 65 | for( i = 0; i <100; i++ ) 66 | { 67 | ets_sprintf( ct, "%02x ", innerbuf[i] ); 68 | uart0_sendStr( ct ); 69 | } 70 | 71 | uint32_t * inner8next = innerbuf; 72 | inner8next = inner8next[5]; 73 | ets_sprintf( ct, "\nInner [8][5]: %p\n", inner8next ); //Nothing more here. 74 | uart0_sendStr( ct ); 75 | for( i = 0; i <100; i++ ) 76 | { 77 | ets_sprintf( ct, "%02x ", ((uint8_t*)inner8next)[i] ); 78 | uart0_sendStr( ct ); 79 | } 80 | #endif 81 | } 82 | 83 | 84 | void SetupRawsend() 85 | { 86 | int i; 87 | for( i = 0; i <7; i++ ) 88 | { 89 | ppRegisterTxCallback( txcb, i ); 90 | } 91 | } 92 | 93 | int CanRawsend() 94 | { 95 | return pxpkt!=0; 96 | } 97 | 98 | //I don't use this anymore, so really no need to do it. 99 | //I strongly recommend using esp freedom if possible. 100 | void RawSendBuffer( uint8_t * buffer, int length ) 101 | { 102 | if( !pxpkt ) 103 | { 104 | printf( "Nosend." ); 105 | return; 106 | } 107 | 108 | struct Ctrl{ 109 | uint8_t reserved; //No idea 110 | uint8_t channel:4; //This is a guess 111 | uint8_t size_lsb:4; 112 | uint8_t size_msb; //This is almost always 192. 113 | uint8_t code; 114 | } * control = ((struct Ctrl**)pxpkt)[1]; 115 | 116 | #ifdef DO_DEEP_TX_DEBUG 117 | char buffer[100]; 118 | ets_sprintf( buffer, "Res: %d Chan: %d Size: %d Code: %d // TXLen: %d\n", control->reserved, control->channel, control->size_lsb + (control->size_msb<<4), control->code, ((uint32_t*)pxpkt)[5]>>16 ); 119 | uart0_sendStr(buffer); 120 | #endif 121 | 122 | int size = length; //Actual size of payload. 123 | if( size < 24 ) size = 24; 124 | 125 | control->size_lsb = size&0x0f; 126 | control->size_msb = size>>4; 127 | ((uint32_t*)pxpkt)[5] = (((uint32_t*)pxpkt)[5] & 0xff ) | ((size-24)<<16); 128 | 129 | uint8_t * rawpacket = ((uint8_t**)pxpkt)[4]; 130 | ets_memcpy( rawpacket, buffer, length ); 131 | ppTxPkt( pxpkt ); 132 | 133 | } 134 | 135 | 136 | -------------------------------------------------------------------------------- /web/page/main.js: -------------------------------------------------------------------------------- 1 | //Copyright (C) 2015 <>< Charles Lohr, see LICENSE file for more info. 2 | // 3 | //This particular file may be licensed under the MIT/x11, New BSD or ColorChord Licenses. 4 | 5 | var mements = 16; 6 | 7 | 8 | function KickMEMCTRL() 9 | { 10 | MEMCTRLDataTicker(); 11 | } 12 | 13 | 14 | 15 | window.addEventListener("load", KickMEMCTRL, false); 16 | 17 | function CommitVal( which ) 18 | { 19 | var addy = parseInt( $("#ent"+which).val() ); 20 | if( addy <= 0 ) return; 21 | var typ = $("input[name=typ"+which+"]:checked").val(); 22 | if( typ == 'r' ) 23 | { 24 | QueueOperation( "CR\t" + addy, GotMemR, which ); 25 | console.log( "CR\t" + addy ); 26 | } 27 | else if( typ == 'o' ) 28 | { 29 | var cmd = "CW\t" + addy + "\t" + parseInt( $("#val"+which).val() ); 30 | QueueOperation( cmd, GotMemW, which ); 31 | } 32 | 33 | } 34 | 35 | function GotMemR(req,data) 36 | { 37 | var v = data.split( "\t" ); 38 | $("#val"+req.extra).val( "0x" + parseInt(v[1]).toString(16) ); 39 | } 40 | 41 | function GotMemW(req,data) 42 | { 43 | } 44 | 45 | var storage = ""; 46 | 47 | function MEMCTRLDataTicker() 48 | { 49 | if( IsTabOpen('MEMCTRL') ) { 50 | memplace = -1; 51 | storage = ""; 52 | QueueOperation( "CD", GotMEM, -1 ); 53 | } 54 | } 55 | 56 | function SaveParams() 57 | { 58 | var storage = ""; 59 | for( var memplace = 0; memplace < mements; memplace++ ) 60 | { 61 | var typ = $("input[name=typ" +memplace+ "]:checked").val(); 62 | storage += $("#ent"+memplace).val() + "\t" + typ + "\t"; 63 | storage += $("#val"+memplace).val() + "\n"; 64 | } 65 | localStorage.memstore = storage; 66 | } 67 | 68 | function GotMEM(req,data) 69 | { 70 | var v = data.split( "\t" ); 71 | if( !IsTabOpen('MEMCTRL') ) 72 | { 73 | return; 74 | } 75 | $("#memplace").val( memplace ); 76 | 77 | if( req.extra == -1 ) 78 | { 79 | $("#memdebug").val( v[1] ); 80 | $("#memdebug2").val( v[2] ); 81 | } 82 | else 83 | { 84 | $("#val"+req.extra).val( "0x" + parseInt(v[1]).toString(16) ); 85 | } 86 | 87 | memplace++; 88 | 89 | if( memplace < mements ) 90 | { 91 | var typ = $("input[name=typ" +memplace+ "]:checked").val(); 92 | addy = parseInt( $("#ent"+memplace).val() ); 93 | if( typ == 'w' && addy > 0 ) //Watch 94 | { 95 | QueueOperation( "CR\t" + addy, GotMEM, memplace ); 96 | } 97 | else 98 | { 99 | QueueOperation( "CD", GotMEM, -1 ); 100 | } 101 | } 102 | else 103 | { 104 | memplace = -1; 105 | SaveParams(); 106 | QueueOperation( "CD", GotMEM, -1 ); 107 | } 108 | 109 | //console.log( data ); 110 | } 111 | 112 | 113 | $(document).ready(function () { 114 | var dasent = ""; 115 | for( var i = 0; i < mements; i++ ) 116 | { 117 | let iv = i; 118 | dasent += ""; 119 | } 120 | $("#controllist").html( dasent + "
addressNoneInputWatchOutputValueSubmit
NoneInputWatchOutput
" ); 121 | 122 | if( localStorage.memstore ) 123 | { 124 | var lines = localStorage.memstore.split( "\n" ); 125 | for( var i = 0; i < lines.length; i++ ) 126 | { 127 | var sp = lines[i].split( "\t" ); 128 | if( sp.length < 3 ) continue; 129 | $("#ent"+i).val(sp[0]); 130 | if( sp[1] == 'n' ) $("input[name=typ" +i+ "]")[0].checked = true; 131 | if( sp[1] == 'i' ) $("input[name=typ" +i+ "]")[1].checked = true; 132 | if( sp[1] == 'w' ) $("input[name=typ" +i+ "]")[2].checked = true; 133 | if( sp[1] == 'o' ) $("input[name=typ" +i+ "]")[3].checked = true; 134 | $("#val"+i).val(sp[2]); 135 | } 136 | } 137 | }); 138 | 139 | 140 | -------------------------------------------------------------------------------- /web/page/page.old/main.js: -------------------------------------------------------------------------------- 1 | //Copyright (C) 2015 <>< Charles Lohr, see LICENSE file for more info. 2 | // 3 | //This particular file may be licensed under the MIT/x11, New BSD or ColorChord Licenses. 4 | 5 | var mements = 16; 6 | 7 | 8 | function KickMEMCTRL() 9 | { 10 | MEMCTRLDataTicker(); 11 | } 12 | 13 | 14 | 15 | window.addEventListener("load", KickMEMCTRL, false); 16 | 17 | function CommitVal( which ) 18 | { 19 | var addy = parseInt( $("#ent"+which).val() ); 20 | if( addy <= 0 ) return; 21 | var typ = $("input[name=typ"+which+"]:checked").val(); 22 | if( typ == 'r' ) 23 | { 24 | QueueOperation( "CR\t" + addy, GotMemR, which ); 25 | console.log( "CR\t" + addy ); 26 | } 27 | else if( typ == 'o' ) 28 | { 29 | var cmd = "CW\t" + addy + "\t" + parseInt( $("#val"+which).val() ); 30 | QueueOperation( cmd, GotMemW, which ); 31 | } 32 | 33 | } 34 | 35 | function GotMemR(req,data) 36 | { 37 | var v = data.split( "\t" ); 38 | $("#val"+req.extra).val( "0x" + parseInt(v[1]).toString(16) ); 39 | } 40 | 41 | function GotMemW(req,data) 42 | { 43 | } 44 | 45 | var storage = ""; 46 | 47 | function MEMCTRLDataTicker() 48 | { 49 | if( IsTabOpen('MEMCTRL') ) { 50 | memplace = -1; 51 | storage = ""; 52 | QueueOperation( "CD", GotMEM, -1 ); 53 | } 54 | } 55 | 56 | function SaveParams() 57 | { 58 | var storage = ""; 59 | for( var memplace = 0; memplace < mements; memplace++ ) 60 | { 61 | var typ = $("input[name=typ" +memplace+ "]:checked").val(); 62 | storage += $("#ent"+memplace).val() + "\t" + typ + "\t"; 63 | storage += $("#val"+memplace).val() + "\n"; 64 | } 65 | localStorage.memstore = storage; 66 | } 67 | 68 | function GotMEM(req,data) 69 | { 70 | var v = data.split( "\t" ); 71 | if( !IsTabOpen('MEMCTRL') ) 72 | { 73 | return; 74 | } 75 | $("#memplace").val( memplace ); 76 | 77 | if( req.extra == -1 ) 78 | { 79 | $("#memdebug").val( v[1] ); 80 | $("#memdebug2").val( v[2] ); 81 | } 82 | else 83 | { 84 | $("#val"+req.extra).val( "0x" + parseInt(v[1]).toString(16) ); 85 | } 86 | 87 | memplace++; 88 | 89 | if( memplace < mements ) 90 | { 91 | var typ = $("input[name=typ" +memplace+ "]:checked").val(); 92 | addy = parseInt( $("#ent"+memplace).val() ); 93 | if( typ == 'w' && addy > 0 ) //Watch 94 | { 95 | QueueOperation( "CR\t" + addy, GotMEM, memplace ); 96 | } 97 | else 98 | { 99 | QueueOperation( "CD", GotMEM, -1 ); 100 | } 101 | } 102 | else 103 | { 104 | memplace = -1; 105 | SaveParams(); 106 | QueueOperation( "CD", GotMEM, -1 ); 107 | } 108 | 109 | //console.log( data ); 110 | } 111 | 112 | 113 | 114 | 115 | $(document).ready(function () { 116 | var dasent = ""; 117 | for( var i = 0; i < mements; i++ ) 118 | { 119 | let iv = i; 120 | dasent += ""; 121 | } 122 | $("#controllist").html( dasent + "
addressNoneInputWatchOutputValueSubmit
NoneInputWatchOutput
" ); 123 | 124 | if( localStorage.memstore ) 125 | { 126 | var lines = localStorage.memstore.split( "\n" ); 127 | for( var i = 0; i < lines.length; i++ ) 128 | { 129 | var sp = lines[i].split( "\t" ); 130 | if( sp.length < 3 ) continue; 131 | $("#ent"+i).val(sp[0]); 132 | if( sp[1] == 'n' ) $("input[name=typ" +i+ "]")[0].checked = true; 133 | if( sp[1] == 'i' ) $("input[name=typ" +i+ "]")[1].checked = true; 134 | if( sp[1] == 'w' ) $("input[name=typ" +i+ "]")[2].checked = true; 135 | if( sp[1] == 'o' ) $("input[name=typ" +i+ "]")[3].checked = true; 136 | $("#val"+i).val(sp[2]); 137 | } 138 | } 139 | }); 140 | 141 | 142 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Demonstration of raw packet sending on the ESP8266 for the purpose of triangulation. 2 | 3 | NOW 2.0.0 COMPATIBLE. see https://github.com/cnlohr/esp8266rawpackets/issues/7 4 | 5 | ## Introduction 6 | This project is geared for the end attempt at triangulation (Which it can't do currently) but, I have run into some useful things along the way. Right now, this allows us to connect to an AP at the same time as send/receive arbitrary packets as well as get timestamps on both the sending and receiving. 7 | 8 | I use the tactic outlined here: https://github.com/ernacktob/esp8266_wifi_raw to override aaEnqueueRxq. I am compiling against 1.5.4. Any other version will require libpp.a to be patched. This mechanism allows us to intercet message packet receives by overriding that function. Once overridden, all broadcast and packets targeted for our host will roll on in! We can process them any way we want. see esp_rawsend.c. Keep in mind this isn't true promiscuous mode, as it does not receive packets that are unicasted to a specific node but not this node. 9 | 10 | Sending raw packets is done by directly calling the esp ```wifi_send_pkt_freedom``` function. I had originaly written ```RawSendBuffer```, but it seems less reliable. For this test, I send data packets to broadcast, but use a special tag to identify them as my packets "82668266" type. 11 | 12 | By using the custom build script, custom.ld, either the NMI or the User interrupt can be overridden. The custom interrupt handler in this case looks for packets with the packet type 0x82668266. If so, it writes in the CCOUNT that happened when the interrupt fired. This isn't very good since if there are two packets that come in one after another, or the interrupt is in use for a different cause, it will make sure the packet is skipped, or has inaccurate time. If a packet is missing entirelly, the time code will be 0. It is important to always remember the timecode may be very inaccurate and can be thrown out. 13 | 14 | As it stands, the ESPs expect to be connected to a wifi network and will send all 82668266 packets back to a host at a fixed ip via ```pUdpServer``` - this means the host that is expecting the packets should be on the connected wifi network at 192.168.1.113, port 9999. The packets returned contain the standard Espressif wifi stack header. 15 | 16 | ## Collecting the data 17 | 18 | We can now run a host at 192.168.1.113. This host can bind to UDP port 9999 and collect all data from all ESPs on the network. An example of this app can be found in toprecorder. Data can be redirected to a data file. Once recorded the data can be processed. 19 | 20 | An enterprising young soul, should they choose could probably process the data in real time, if they so chose. 21 | 22 | ## 2D/3D Localization 23 | 24 | This is where things get tricky. Unlike GPS where we know the time of sending a packet, we can only really trust the time of packet reception. Additionally, we don't know anything about the times on the sending nodes. The only thing we can do is know the time a node sent a packet on a receiver's local oscillator time - we can determine the send time on the initial constellation by subtracting out the distance from one node to another. 25 | 26 | We can synchronize nodes's clocks to one another only when two nodes receive the same packet. We can then know they're at the same time (barring outliers due to the interrupt happening at the wrong time). Once we do this for a while, we can get a pretty good idea what the time on one node would mean for another node. Over a little longer while, we can start to find the clock skew between the nodes and calibrate it back out. 27 | 28 | If we wanted to find the location of a node within the constelaltion that we didn't know the locaiton of, we could transmit, then, look at the differential receive times on that node. This can tell us the relative distances of the transmitter to each node. There is no way to know the absolute distance unless we can be completely confident we can synchronize it's clock and that we can get transmit time. 29 | 30 | There is a jitter of +/-4 clock ticks, so it would take many, many readings to get a good solid reading on what the true differential value would be. 31 | 32 | It's important to note that in our example, all of the nodes are co-planar, so only 2D localization would be possible anyway. I recommend trying to resolve the location of node #5 to the constellation of 1-4 if you want to try to find something. 33 | 34 | ## Why it's hard. 35 | 36 | So, this is a hard question to answer. I think the biggest problem I have with my data is that I'm not very good at analyzing these sorts of things. Additionally, I think I'm fighting clock jitter. Though all crystals have natural speed differences which can be observed, easily in the +/- 5-10ppm range, the crystals also seem to have a random walk which makes it very, very hard to nail down times. Also, figuring out time synchronization from the differential systems is... hard :( - mathematically. 37 | 38 | I've tried doing this a number of times, and I've checked my math by changing the "distance" between nodes to make sure the distances of the true constellation should match that of the data --- and often, they don't :(. 39 | 40 | This data is outside and ideal. Multipath could mess things up! Def need too look at all the encoding schemes. Extra packets might be messing with the timing. Could consider sending data back via serial or Ethernet? 41 | 42 | Also, maybe you could use rssi to help resolve? 43 | -------------------------------------------------------------------------------- /custom_ld.ld: -------------------------------------------------------------------------------- 1 | /* This linker script generated from xt-genldscripts.tpp for LSP . */ 2 | /* Linker Script for ld -N */ 3 | MEMORY 4 | { 5 | dport0_0_seg : org = 0x3FF00000, len = 0x10 6 | dram0_0_seg : org = 0x3FFE8000, len = 0x14000 7 | iram1_0_seg : org = 0x40100000, len = 0x8000 8 | irom0_0_seg : org = 0x40240000, len = 0x3C000 9 | } 10 | 11 | PHDRS 12 | { 13 | dport0_0_phdr PT_LOAD; 14 | dram0_0_phdr PT_LOAD; 15 | dram0_0_bss_phdr PT_LOAD; 16 | iram1_0_phdr PT_LOAD; 17 | irom0_0_phdr PT_LOAD; 18 | } 19 | 20 | 21 | /* Default entry point: */ 22 | ENTRY(call_user_start) 23 | EXTERN(_DebugExceptionVector) 24 | EXTERN(_DoubleExceptionVector) 25 | EXTERN(_KernelExceptionVector) 26 | EXTERN(_NMIExceptionVector) 27 | EXTERN(replacement_USER_vect) 28 | EXTERN(_UserExceptionVector) 29 | PROVIDE(_memmap_vecbase_reset = 0x40000000); 30 | /* Various memory-map dependent cache attribute settings: */ 31 | _memmap_cacheattr_wb_base = 0x00000110; 32 | _memmap_cacheattr_wt_base = 0x00000110; 33 | _memmap_cacheattr_bp_base = 0x00000220; 34 | _memmap_cacheattr_unused_mask = 0xFFFFF00F; 35 | _memmap_cacheattr_wb_trapnull = 0x2222211F; 36 | _memmap_cacheattr_wba_trapnull = 0x2222211F; 37 | _memmap_cacheattr_wbna_trapnull = 0x2222211F; 38 | _memmap_cacheattr_wt_trapnull = 0x2222211F; 39 | _memmap_cacheattr_bp_trapnull = 0x2222222F; 40 | _memmap_cacheattr_wb_strict = 0xFFFFF11F; 41 | _memmap_cacheattr_wt_strict = 0xFFFFF11F; 42 | _memmap_cacheattr_bp_strict = 0xFFFFF22F; 43 | _memmap_cacheattr_wb_allvalid = 0x22222112; 44 | _memmap_cacheattr_wt_allvalid = 0x22222112; 45 | _memmap_cacheattr_bp_allvalid = 0x22222222; 46 | PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); 47 | 48 | SECTIONS 49 | { 50 | 51 | .dport0.rodata : ALIGN(4) 52 | { 53 | _dport0_rodata_start = ABSOLUTE(.); 54 | *(.dport0.rodata) 55 | *(.dport.rodata) 56 | _dport0_rodata_end = ABSOLUTE(.); 57 | } >dport0_0_seg :dport0_0_phdr 58 | 59 | .dport0.literal : ALIGN(4) 60 | { 61 | _dport0_literal_start = ABSOLUTE(.); 62 | *(.dport0.literal) 63 | *(.dport.literal) 64 | _dport0_literal_end = ABSOLUTE(.); 65 | } >dport0_0_seg :dport0_0_phdr 66 | 67 | .dport0.data : ALIGN(4) 68 | { 69 | _dport0_data_start = ABSOLUTE(.); 70 | *(.dport0.data) 71 | *(.dport.data) 72 | _dport0_data_end = ABSOLUTE(.); 73 | } >dport0_0_seg :dport0_0_phdr 74 | 75 | .data : ALIGN(4) 76 | { 77 | _data_start = ABSOLUTE(.); 78 | *(.data) 79 | *(.data.*) 80 | *(.gnu.linkonce.d.*) 81 | *(.data1) 82 | *(.sdata) 83 | *(.sdata.*) 84 | *(.gnu.linkonce.s.*) 85 | *(.sdata2) 86 | *(.sdata2.*) 87 | *(.gnu.linkonce.s2.*) 88 | *(.jcr) 89 | _data_end = ABSOLUTE(.); 90 | } >dram0_0_seg :dram0_0_phdr 91 | 92 | .rodata : ALIGN(4) 93 | { 94 | _rodata_start = ABSOLUTE(.); 95 | *(.sdk.version) 96 | *(.rodata) 97 | *(.rodata.*) 98 | *(.gnu.linkonce.r.*) 99 | *(.rodata1) 100 | __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); 101 | *(.xt_except_table) 102 | *(.gcc_except_table) 103 | *(.gnu.linkonce.e.*) 104 | *(.gnu.version_r) 105 | *(.eh_frame) 106 | /* C++ constructor and destructor tables, properly ordered: */ 107 | KEEP (*crtbegin.o(.ctors)) 108 | KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) 109 | KEEP (*(SORT(.ctors.*))) 110 | KEEP (*(.ctors)) 111 | KEEP (*crtbegin.o(.dtors)) 112 | KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) 113 | KEEP (*(SORT(.dtors.*))) 114 | KEEP (*(.dtors)) 115 | /* C++ exception handlers table: */ 116 | __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); 117 | *(.xt_except_desc) 118 | *(.gnu.linkonce.h.*) 119 | __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); 120 | *(.xt_except_desc_end) 121 | *(.dynamic) 122 | *(.gnu.version_d) 123 | . = ALIGN(4); /* this table MUST be 4-byte aligned */ 124 | _bss_table_start = ABSOLUTE(.); 125 | LONG(_bss_start) 126 | LONG(_bss_end) 127 | _bss_table_end = ABSOLUTE(.); 128 | _rodata_end = ABSOLUTE(.); 129 | } >dram0_0_seg :dram0_0_phdr 130 | 131 | .bss ALIGN(8) (NOLOAD) : ALIGN(4) 132 | { 133 | . = ALIGN (8); 134 | _bss_start = ABSOLUTE(.); 135 | *(.dynsbss) 136 | *(.sbss) 137 | *(.sbss.*) 138 | *(.gnu.linkonce.sb.*) 139 | *(.scommon) 140 | *(.sbss2) 141 | *(.sbss2.*) 142 | *(.gnu.linkonce.sb2.*) 143 | *(.dynbss) 144 | *(.bss) 145 | *(.bss.*) 146 | *(.gnu.linkonce.b.*) 147 | *(COMMON) 148 | . = ALIGN (8); 149 | _bss_end = ABSOLUTE(.); 150 | _heap_start = ABSOLUTE(.); 151 | /* _stack_sentry = ALIGN(0x8); */ 152 | } >dram0_0_seg :dram0_0_bss_phdr 153 | /* __stack = 0x3ffc8000; */ 154 | 155 | .text : ALIGN(4) 156 | { 157 | _stext = .; 158 | _text_start = ABSOLUTE(.); 159 | *(.UserEnter.text) 160 | . = ALIGN(16); 161 | *(.DebugExceptionVector.text) 162 | . = ALIGN(16); 163 | *(.NMIExceptionVector.text) 164 | . = ALIGN(16); 165 | *(.KernelExceptionVector.text) 166 | LONG(0) 167 | LONG(0) 168 | LONG(0) 169 | LONG(0) 170 | . = ALIGN(16); 171 | *(.relocuser.text) 172 | LONG(0) 173 | . = ALIGN(16); 174 | *(.DoubleExceptionVector.text) 175 | LONG(0) 176 | LONG(0) 177 | LONG(0) 178 | LONG(0) 179 | . = ALIGN (16); 180 | *(.entry.text) 181 | *(.init.literal) 182 | *(.init) 183 | *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) 184 | *(.fini.literal) 185 | *(.fini) 186 | *(.gnu.version) 187 | _text_end = ABSOLUTE(.); 188 | _etext = .; 189 | } >iram1_0_seg :iram1_0_phdr 190 | 191 | .lit4 : ALIGN(4) 192 | { 193 | _lit4_start = ABSOLUTE(.); 194 | *(*.lit4) 195 | *(.lit4.*) 196 | *(.gnu.linkonce.lit4.*) 197 | _lit4_end = ABSOLUTE(.); 198 | } >iram1_0_seg :iram1_0_phdr 199 | 200 | .irom0.text : ALIGN(4) 201 | { 202 | _irom0_text_start = ABSOLUTE(.); 203 | *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) 204 | _irom0_text_end = ABSOLUTE(.); 205 | } >irom0_0_seg :irom0_0_phdr 206 | } 207 | 208 | /* get ROM code address */ 209 | INCLUDE "../ld/eagle.rom.addr.v6.ld" 210 | -------------------------------------------------------------------------------- /user/customnmi.S: -------------------------------------------------------------------------------- 1 | #define USER_OVERRIDE 2 | //#define NMI_OVERRIDE 3 | 4 | //#define USE_wDevTime //Only gives you to the us. 5 | 6 | 7 | #ifdef USER_OVERRIDE 8 | .section .text 9 | 10 | .align 4 11 | 12 | 13 | 14 | .global packet_tx_time 15 | 16 | //_addy_of_packet_tx_matchmask: 17 | // .long packet_tx_matchmask 18 | _addy_of_packet_tx_time: 19 | .long packet_tx_time 20 | _lendmark: 21 | .long debugccount 22 | _gpiomark_out: 23 | .long 0x60000304 //Pin_set and 308 is pin_Clear 24 | _interrupt_cause_loc: 25 | .long 0x3ff20c24 26 | _check_against_loc: 27 | .long debugcontrol 28 | 29 | .global PreEmpt_USER_Vector 30 | PreEmpt_USER_Vector: 31 | // movi a0, 3 32 | 33 | #if 1 34 | addi a1, a1, -16 35 | s32i a2, a1, 4 36 | s32i a3, a1, 8 37 | s32i a4, a1, 12 38 | 39 | // rsr a2, intenable 40 | // rsr a3, interrupt 41 | // and a2, a2, a3 //Should also mask off 0x3fff but I'm not worried about it. 42 | 43 | rsr a2, interrupt //We are only looking at bit 0 and the wifi chip should be enabled.s 44 | 45 | //Make sure it's a wifi interrupt. 46 | bbci a2, 0, _skip_er //INUM_WDEV_FIQ = 0 47 | 48 | //Next, make sure it's an actual RX interrupt. 49 | movi a2, 0x3ff20c20 50 | l32i a3, a2, 0 51 | 52 | #ifdef DEBUG_BITMASK 53 | movi a2, debugcontrol //0x0100 looks good. 54 | l32i a2, a2, 0 55 | and a3, a2, a3 56 | beqz a3, _skip_er 57 | #else 58 | bbci a3, 8, _skip_er_maybe_trigger_tx 59 | #endif 60 | 61 | 62 | //TODO: Look at 0x3ff20c84, it flips between 0x2200 and 0x00 63 | //TODO TODO: Look at 0x3ff210fc -> May be CCOUNT of incoming packet!!! 64 | //0x3ff2001c contains a pointer to ram -> which starts with 0xc0068640 ... 0x3ffedcec ... 0x3ffec9f4 ... (0 or 0x80640640) (0 or pointer) 65 | //0x3ff20014 contains a pointer to ram -> which starts with 0xc0074640 ... 0x3ffedcec ... 0x3ffec9f4 ... (0 or 0x80640640) (0 or pointer) 66 | //0x3ffec9f4 -> 0x80640640 67 | //0x3ffedcec -> 0x50154b26 (changes on RSSI), 0x97007107(or0), 0, 0x2c4288, 0xc07fcf5c (or 0xffffffff), 0x9fc25560, 0x40d823db 68 | // 69 | movi a2, 0x3ff2001c 70 | l32i a2, a2, 0 //Get pointer to memory structre 71 | l32i a2, a2, 4 //Second word in structure 72 | l32i a3, a2, (12+24) //12 is beginning of packet. We're loking 24 bytes in. 73 | 74 | movi a4, 0x66826682 75 | bne a4, a3, _skip_er 76 | 77 | l32i a3, a2, (12+24+16) //Where the time goes (make sure it's 0) 78 | bnez a3, _skip_er 79 | 80 | #ifdef USE_wDevTime 81 | movi a3, 0x3ff210fc 82 | l32i a0, a3, 0 83 | #endif 84 | s32i a0, a2, (12+24+16) //Write in A0 (Ccount) XXX TODO consider bumming 0x3ff210fc 85 | 86 | 87 | l32r a2, _lendmark 88 | s32i a0, a2, 0 89 | //Tick on the logic analyzer to test precision of interrupts. 90 | movi a0, 4 91 | 92 | //Twiddle GPIO 93 | l32r a2, _gpiomark_out 94 | s32i a0, a2, 0 95 | s32i a0, a2, 4 96 | j _skip_er 97 | 98 | //////////////////////////////////////////////////////////////////////////////////////////////// 99 | ////////////////////////////////Get precise time of tx packets 100 | 101 | _skip_er_maybe_trigger_tx: 102 | 103 | // vvv Change this number!!! 104 | //bbci a3, 7, _skip_er //XXX XXX TODO HERE NEED RX interrupt notice. 105 | //Notes: 106 | // 0x00040000 = Kind of TX? Not perfect, tho. (Bit 18) 107 | // 0x00080000 = Kind of TX? Seems worse than 0x00040000... Acks too? 108 | 109 | /* 110 | l32r a2, _addy_of_packet_tx_matchmask 111 | l32i a2, a2, 0 112 | and a2, a2, a3 113 | beqz a2, _skip_er 114 | */ 115 | bbci a3, 18, _skip_er 116 | 117 | l32r a2, _addy_of_packet_tx_time 118 | l32i a3, a2, 0 119 | bnez a3, _skip_er 120 | s32i a0, a2, 0 121 | 122 | _skip_er: 123 | 124 | l32i a2, a1, 4 125 | l32i a3, a1, 8 126 | l32i a4, a1, 12 127 | 128 | addi a1, a1, 16 129 | #endif 130 | _call0 _UserExceptionVector_1 131 | 132 | #endif 133 | 134 | 135 | #ifdef NMI_OVERRIDE 136 | .align 4 137 | 138 | .global debugccount 139 | .global PreEmpt_NMI_Vector 140 | _lendmark2b: 141 | .long debugccount2 142 | PreEmpt_NMI_Vector: 143 | addi a1, a1, -8 144 | s32i a2, a1, 4 145 | l32r a2, _lendmark2b 146 | s32i a0, a2, 0 147 | l32i a2, a1, 4 148 | addi a1, a1, 8 149 | // rsr a0, execsave3 150 | // rfi 3 151 | _call0 _NMILevelVector 152 | #endif 153 | 154 | 155 | #ifdef USER_OVERRIDE 156 | 157 | //This code will be memcpy'd over top of _UserExceptionVector, since I can't figure out how to override it with GCC. 158 | .section .relocuser.text 159 | .global replacement_USER_vect 160 | .align 4 161 | replacement_USER_vect: 162 | _wsr.excsave1 a0 163 | 164 | // _call0 _UserExceptionVector_1 165 | 166 | rsr a0, ccount 167 | j PreEmpt_USER_Vector 168 | 169 | #endif 170 | 171 | #ifdef NMI_OVERRIDE 172 | 173 | //This code will be memcpy'd over top of _UserExceptionVector, since I can't figure out how to override it with GCC. 174 | .section .relocvec.text 175 | .global replacement_NMI_vect 176 | .align 4 177 | replacement_NMI_vect: 178 | //Original code. 179 | //40100020: 13d300 wsr.excsave3 a0 180 | //40100023: 014d05 call0 401014f4 <_NMILevelVector> 181 | //wsr a0, execsave3 182 | .byte 0x00 183 | .byte 0xd3 184 | .byte 0x13 185 | // _call0 _NMILevelVector 186 | 187 | #ifndef USE_wDevTime 188 | rsr a0, ccount 189 | #endif 190 | j PreEmpt_NMI_Vector 191 | // ill 192 | 193 | #endif 194 | 195 | 196 | /* 197 | 198 | //.section .irom0.text 199 | .section .text 200 | 201 | //Originally I thought this part had to be in ASM, it does not. 202 | .global wifi_mcb; 203 | .global aaEnqueueRxq 204 | .align 4 205 | //wifilocator: 206 | // .long wifi_mcb 207 | aaEnqueueRxq: 208 | _addi a1, a1, -68 209 | _s32i.n a0, a1, 0 210 | _s32i.n a2, a1, 4 211 | _s32i.n a3, a1, 8 212 | _s32i.n a4, a1, 12 213 | _s32i.n a5, a1, 16 214 | _s32i.n a6, a1, 20 215 | _s32i.n a7, a1, 24 216 | _s32i.n a8, a1, 28 217 | _s32i.n a9, a1, 32 218 | _s32i.n a10, a1, 36 219 | _s32i.n a11, a1, 40 220 | _s32i.n a12, a1, 44 221 | _s32i.n a13, a1, 48 222 | _s32i.n a14, a1, 52 223 | _s32i.n a15, a1, 56 224 | 225 | 226 | // l32r a0, wifilocator 227 | // l32i a0, a0, 0 228 | // beqz a0, __skip 229 | // callx0 a0 230 | // __skip: 231 | 232 | 233 | l32i a3, a2, 0 234 | l32i a4, a2, 4 235 | l32i a5, a2, 8 236 | l32i a6, a2, 12 237 | l32i a2, a2, 16 238 | call0 rx_func 239 | 240 | _l32i.n a0, a1, 0 241 | _l32i.n a2, a1, 4 242 | _l32i.n a3, a1, 8 243 | _l32i.n a4, a1, 12 244 | _l32i.n a5, a1, 16 245 | _l32i.n a6, a1, 20 246 | _l32i.n a7, a1, 24 247 | _l32i.n a8, a1, 28 248 | _l32i.n a9, a1, 32 249 | _l32i.n a10, a1, 36 250 | _l32i.n a11, a1, 40 251 | _l32i.n a12, a1, 44 252 | _l32i.n a13, a1, 48 253 | _l32i.n a14, a1, 52 254 | _l32i.n a15, a1, 56 255 | _addi a1, a1, 68 256 | 257 | j ppEnqueueRxq 258 | */ 259 | -------------------------------------------------------------------------------- /notes.txt: -------------------------------------------------------------------------------- 1 | Charles notes: 2 | 3 | 192.168.11.169 < default sender. 4 | 192.168.11.147 < other guy. 5 | 6 | 7 | additional notes: 8 | 9 | https://github.com/ernacktob/esp8266_wifi_raw 10 | ^^ This guy wins. 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | https://github.com/SuperHouse/esp-open-rtos/issues/4 22 | 23 | Consider: eagle_lwip_getif 24 | 25 | A second step would be writing a function in C that replicates the ieee80211_send_probereq, 26 | basically creating a management frame using ieee80211_getmgtframe, configuring it and finally outputting the frame via ieee80211_mgmt_output which internally calls ieee80211_raw_output which in my opinion is replaced by ppTxPkt in ESP, so maybe the signature is similar. But I didn't go down that road so much. Help would be appreciated. 27 | 28 | http://www.esp8266.com/viewtopic.php?f=6&t=3481&p=19857&hilit=ppTxPkt#p19857 29 | 30 | 31 | 32 | 33 | 34 | 35 | //ieee80211_output_pbuf here: 36 | https://github.com/kadamski/esp-lwip/blob/esp8266-1.4.1/our/eagle_lwip_if.c 37 | 38 | 39 | 40 | 41 | Also.. 42 | The very answer to your question. 43 | With ieee80211_output_pbuf can be sent only ethernet packets. Campaign you need to pick ieee80211_send_mgmt, but already there is a dark forest. 44 | 45 | Dispatch is ppTxPkt (void * x), where x + 0x20 some pointer ... 46 | ieee80211_send_mgmt inserts poppies - Net handles wifi frame in the frame. 47 | 48 | 49 | 50 | 51 | 52 | https://github.com/angelovAlex/esp-blobs/tree/c8d4d39b9137c5c32a464fee223dd71ec686f4d6 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | Some really excessive code: 68 | 69 | //I have no found this function is useless. 70 | //struct ieee80211_node * eagle_lwip_getif(int id); //Always make id = 1; 71 | 72 | void * pxpkt = 0; 73 | 74 | static void txcb(uint8_t *buf, uint16 reason) 75 | { 76 | pxpkt = buf; 77 | return; 78 | char ct[16]; 79 | int i = 0; 80 | ets_sprintf( ct, "<%p %d --> NODE:%p\n", buf, reason, eagle_lwip_getif(1) ); 81 | uart0_sendStr( ct ); 82 | for( i = 0; i <100; i++ ) 83 | { 84 | ets_sprintf( ct, "%02x ", buf[i] ); 85 | uart0_sendStr( ct ); 86 | } 87 | uart0_sendStr( "\n" ); 88 | 89 | uint8_t * innerbuf = ((uint32_t*)buf)[1]; 90 | ets_sprintf( ct, "\nInner [1]: %p\n", innerbuf ); 91 | uart0_sendStr( ct ); 92 | 93 | for( i = 0; i <100; i++ ) 94 | { 95 | ets_sprintf( ct, "%02x ", innerbuf[i] ); 96 | uart0_sendStr( ct ); 97 | } 98 | 99 | innerbuf = ((uint32_t*)buf)[4]; 100 | ets_sprintf( ct, "\nInner [4]: %p\n", innerbuf ); 101 | uart0_sendStr( ct ); 102 | for( i = 0; i <100; i++ ) 103 | { 104 | ets_sprintf( ct, "%02x ", innerbuf[i] ); 105 | uart0_sendStr( ct ); 106 | } 107 | 108 | 109 | innerbuf = ((uint32_t*)buf)[8]; 110 | ets_sprintf( ct, "\nInner [8]: %p\n", innerbuf ); //nothing else here... 111 | uart0_sendStr( ct ); 112 | for( i = 0; i <100; i++ ) 113 | { 114 | ets_sprintf( ct, "%02x ", innerbuf[i] ); 115 | uart0_sendStr( ct ); 116 | } 117 | 118 | uint32_t * inner8next = innerbuf; 119 | inner8next = inner8next[5]; 120 | ets_sprintf( ct, "\nInner [8][5]: %p\n", inner8next ); //Nothing more here. 121 | uart0_sendStr( ct ); 122 | for( i = 0; i <100; i++ ) 123 | { 124 | ets_sprintf( ct, "%02x ", ((uint8_t*)inner8next)[i] ); 125 | uart0_sendStr( ct ); 126 | } 127 | } 128 | 129 | 130 | //Timer event. 131 | static void 132 | myTimer(void *arg) 133 | { 134 | int i; 135 | uart0_sendStr("."); 136 | 137 | #if 0 138 | 139 | uint32_t * pxt[512]; 140 | ets_memset( pxt, 0, sizeof( pxt ) ); 141 | 142 | /* struct A5Struct 143 | { 144 | uint8_t q0; 145 | uint8_t q1; 146 | uint8_t q2; 147 | uint8_t q3; 148 | uint8_t a0; 149 | uint8_t q5; 150 | uint8_t a3; 151 | uint8_t q7; 152 | } a5; 153 | 154 | a5.a0 = 0x06; //??? (extui a0, a0, 0, 4) where the last 2 are shift,mask 155 | a5.a3 = 0x00; //??? (extui a3, a3, 4, 3) 156 | 157 | /* 158 | //a2 is a pointer. 159 | //Make stack 16 bigger. 160 | //Push a0, a12 to stack. 161 | uint8_t * a5 = ((uint8_t*)a2)[8]; (0x20) 162 | uint32_t * a12 = a2; 163 | uint8_t a3 = a5[6]; 164 | uint8_t a0 = a5[4]; 165 | a3 = (a3>>4)&0b111; 166 | a0 = a0 & 0x0f; 167 | if( a0 == 0 || a0 == 3 ) { a2 = 2; } 168 | else if( a0 < 3 ) { a2 = 3; } 169 | else if( a0 < 6 ) { a2 = 1; } 170 | else { a2 = 0 } 171 | if( a2 != a3 ) 172 | { 173 | printf( "%s %u", "pp.c", 146 ); 174 | } 175 | 176 | a2 = a12; (restore pointer) 177 | fun_4024c82c(); 178 | 179 | */ 180 | //If exended a0 is 0, then, it will set a2 to 2 and jump to checker. 181 | //If extended a0 == 3, then it will set a2 to 2, and go to checker. 182 | //If extended a0 < 3, then it will set a2 to 3, and go to checker. 183 | //a2 = 1; 184 | //Then, 185 | //If a0 < 6, then it will immediately go to checker. 186 | //a2 = 0; 187 | //Jump to checker. 188 | // 189 | //checker: 190 | // pxt[8] = &a5; //???? (A5) 191 | 192 | /* for( i = 0; i < 10; i++ ) 193 | { 194 | pxt[i] = eagle_lwip_getif(0);; 195 | }*/ 196 | 197 | struct myin4 198 | { 199 | uint32_t head; 200 | uint8_t macto[6]; 201 | uint8_t macfrom[6]; 202 | uint8_t macfrom2[6]; //vas is stas 203 | uint8_t payload[512]; 204 | }; 205 | 206 | struct aearly 207 | { 208 | uint32_t first; 209 | uint8_t * in4addy; 210 | uint32_t zero; 211 | struct myin4 in4; 212 | } ae; 213 | ae.first = 0xc004d100; //??? MAGIC??? 214 | ae.in4addy = &ae.in4; 215 | ae.zero = 0; 216 | memset( &ae.in4, 0, sizeof( ae.in4 ) ); 217 | ae.in4.head = 0x8; 218 | ae.in4.macto[0] = 0xff;ae.in4.macto[1] = 0xff;ae.in4.macto[2] = 0xff;ae.in4.macto[3] = 0xff;ae.in4.macto[4] = 0xff;ae.in4.macto[5] = 0xff; 219 | ae.in4.macfrom[0] = 0x1a;ae.in4.macfrom[1] = 0xfe;ae.in4.macfrom[2] = 0x34;ae.in4.macfrom[3] = 0x99;ae.in4.macfrom[4] = 0x08;ae.in4.macfrom[5] = 0xa0; 220 | ae.in4.macfrom2[0] = 0x1a;ae.in4.macfrom2[1] = 0xfe;ae.in4.macfrom2[2] = 0x34;ae.in4.macfrom2[3] = 0x99;ae.in4.macfrom2[4] = 0x08;ae.in4.macfrom2[5] = 0xa0; 221 | 222 | struct ain8 223 | { 224 | uint32_t first, second, third, fourth, fifth; 225 | uint32_t * sixth; 226 | uint8_t buffer[100]; 227 | } ain8; 228 | 229 | memset( &ain8, 0, sizeof( ain8 ) ); 230 | 231 | ain8.first = 0x20110486; //??? magic! 232 | ain8.second = 0; 233 | ain8.third = 0x0003327f; //??? magic! 234 | ain8.fourth = 0xad011000; //??? magic! 235 | ain8.fifth = 0x14005bb0; //?? magic! 236 | ain8.sixth = 0x3ffe8214; //This is some constant firmly planted deep within libpp.a(trc.o) 237 | 238 | pxt[0] = 0; 239 | pxt[1] = 0x3ffef5a4; //&ae; libpp.a(esf_buf.o) 240 | pxt[2] = 0x3ffef5a4; //&ae; libpp.a(esf_buf.o) 241 | pxt[3] = 1; 242 | pxt[4] = &ae.in4; //0x3ffef5b0; //&ae.in4; libpp.a(esf_buf.o) 243 | pxt[5] = 0x00350018; //magic!. 244 | pxt[6] = 0; 245 | pxt[7] = 0; 246 | pxt[8] = 0x3ffefa30; //&ain8; 247 | pxt[9] = 0; 248 | pxt[10] = 0x3ffef6b0;//&ain10; (INVESTIGATE) libpp.a(esf_buf.o) 249 | pxt[11] = 0x3ffef6b0;//&ain10; (INVESTIGATE) libpp.a(esf_buf.o) 250 | pxt[12] = 1; 251 | pxt[13] = 0x3ffef6bc; //INVESTIGATE libpp.a(esf_buf.o) 252 | pxt[14] = 0; 253 | pxt[15] = 0; 254 | pxt[16] = 0; 255 | pxt[17] = 0xf3fefa48; //Investigate libpp.a(esf_buf.o) 256 | pxt[18] = 0; 257 | 258 | //There may be more... 259 | 260 | 261 | #endif 262 | 263 | 264 | if( pxpkt ) 265 | { 266 | //control = 00 d1 34 c0 b0 f5 fe 3f 00 00 00 00 267 | struct Ctrl{ 268 | uint8_t reserved; //No idea 269 | uint8_t channel:4; //This is a guess 270 | uint8_t size_lsb:4; 271 | uint8_t size_msb; //This is almost always 192. 272 | uint8_t code; 273 | } * control = ((uint32_t*)pxpkt)[1]; 274 | 275 | char buffer[100]; 276 | ets_sprintf( buffer, "Res: %d Chan: %d Size: %d Code: %d // TXLen: %d\n", control->reserved, control->channel, control->size_lsb + (control->size_msb<<4), control->code, ((uint32_t*)pxpkt)[5]>>16 ); 277 | uart0_sendStr(buffer); 278 | 279 | 280 | //This doesn't work, why? 281 | 282 | int size = 100; //Actual size of payload. 283 | control->size_lsb = size&0x0f; 284 | control->size_msb = size>>4; 285 | ((uint32_t*)pxpkt)[5] = (((uint32_t*)pxpkt)[5] & 0xff ) | ((size-24)<<16); 286 | 287 | 288 | ets_sprintf( buffer, "Res: %d Chan: %d Size: %d Code: %d // TXLen: %d\n", control->reserved, control->channel, control->size_lsb + (control->size_msb<<4), control->code, ((uint32_t*)pxpkt)[5]>>16 ); 289 | uart0_sendStr(buffer); 290 | 291 | 292 | // char buffer[10]; 293 | // int i; 294 | /* for( i = 0; i < 4; i++ ) 295 | { 296 | ets_sprintf( buffer, "%02x ", control[i] ); 297 | uart0_sendStr(buffer); 298 | } 299 | //00 11 06 c0 = 127 bytes. 300 | // 91 09 c0 = 183 bytes. 301 | //00 d1 09 c0 = 187 bytes 302 | //00 51 0a c0 = 195 bytes. 303 | */ 304 | 305 | // uart0_sendStr( "\n" ); 306 | // control[2] = 0x34; //44decimal makes packets 0x51 307 | //0x34 makes packets ??? 308 | 309 | uint8_t * packet = ((uint32_t*)pxpkt)[4]; 310 | memset( packet, 0, 200 ); 311 | packet[0] = 0xff; //0x80 = a beacon. 312 | for( i = 0; i < 255; i++ ) 313 | { 314 | packet[i+4] = i; 315 | } 316 | ppTxPkt( pxpkt ); 317 | } 318 | 319 | // struct ieee80211_node * node = eagle_lwip_getif(0); 320 | // ieee80211_send_nulldata( node ); 321 | } 322 | 323 | -------------------------------------------------------------------------------- /user/user_main.c: -------------------------------------------------------------------------------- 1 | #include "mem.h" 2 | #include "c_types.h" 3 | #include "user_interface.h" 4 | #include "ets_sys.h" 5 | #include 6 | #include "osapi.h" 7 | #include "espconn.h" 8 | #include "esp_rawsend.h" 9 | #include "esp82xxutil.h" 10 | 11 | #define procTaskPrio 0 12 | #define procTaskQueueLen 1 13 | 14 | char generic_print_buffer[384]; 15 | 16 | static struct espconn *pUdpServer; 17 | 18 | static volatile os_timer_t some_timer; 19 | 20 | //Tasks that happen all the time. 21 | os_event_t procTaskQueue[procTaskQueueLen]; 22 | static void ICACHE_FLASH_ATTR 23 | procTask(os_event_t *events) 24 | { 25 | system_os_post(procTaskPrio, 0, 0 ); 26 | 27 | if( events->sig == 0 && events->par == 0 ) 28 | { 29 | //Idle Event. 30 | } 31 | // printf( "+" ); 32 | // ets_delay_us( 20000 ); 33 | // printf( "-" ); 34 | } 35 | 36 | uint8_t mypacket[30+256] = { //256 = max size of additional payload 37 | 0x08, //Frame type, 0x80 = beacon, Tried data, but seems to have been filtered on RX side by other ESP 38 | 0x00, 0x00, 0x00, 39 | 0xff,0xff,0xff,0xff,0xff,0xff, 40 | 0xff,0xff,0xff,0xff,0xff,0xff, 41 | 0xff,0xff,0xff,0xff,0xff,0xff, 42 | 0x00, 0x00, //Sequence number, cleared by espressif 43 | 0x82, 0x66, //"Mysterious OLPC stuff" 44 | 0x82, 0x66, 0x00, 0x00, //???? 45 | 46 | }; 47 | 48 | 49 | 50 | volatile uint32_t debugccount; 51 | volatile uint32_t debugccount2; 52 | volatile uint32_t debugccount3; 53 | volatile uint32_t debugcontrol; 54 | 55 | volatile uint32_t packet_tx_time; 56 | volatile uint32_t packet_tx_matchmask = 0x10000; 57 | 58 | void udpserver_recv(void *arg, char *pusrdata, unsigned short len) 59 | { 60 | struct espconn *pespconn = (struct espconn *)arg; 61 | //Not used. 62 | } 63 | 64 | #define MAX_BUFFERS 10 65 | #define BUFFERSIZE 40 66 | uint8_t buffers[MAX_BUFFERS][BUFFERSIZE]; 67 | uint8_t bufferinuse[MAX_BUFFERS]; 68 | 69 | void __attribute__ ((noinline)) rx_func( struct RxPacket * r, void ** v ) 70 | { 71 | debugccount3++; 72 | if( r->data[24] != 0x82 || r->data[25] != 0x66 || r->data[26] != 0x82 || r->data[27] != 0x66 ) 73 | { 74 | return; 75 | } 76 | 77 | 78 | //debugccount2++; 79 | //printf( "%p = %p %p %p %p %p %p %p %p %p %p\n", v, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9] ); 80 | //3ffeb760 = 3fff0290 3ffecb34 3ffecb34 00000001 3ffede2c 003e001a 0000fff7 00000000 00000000 3ffebdc8 81 | 82 | //v[0] = 3ffff180 3ffff190 00100000 00000000 00000000 00050060 3fff02f8 00000030 00000010 00000003 (Doesn't seem to change) 83 | //v[0][0] = death 84 | //v[0][1] = death 85 | //v[1] = 80038640 3ffed7c8 00000000 (Varying fields afterwards, second value changes a lot) 86 | //v[1][1] = 402e1033 00000000 00010000 00000008 ffffffff cf5cffff 080bc17f ffffffff a7d0ffff 00006682 <<< Looks like payload. 87 | //v[2] = (usually identical v[1]) 88 | //v[4] = same as v[1][1] (packet payload) 89 | /* 90 | uint32_t ** vit = (uint32_t**)v[0]; 91 | uint32_t * vi = (uint32_t*)vit[0]; 92 | int i; 93 | for( i = 0; i < 10; i++ ) 94 | { 95 | printf( "%p ", vi[i] ); 96 | } 97 | printf( "\n" ); 98 | */ 99 | 100 | // ((uint32_t*)r)[1] = watchccount; 101 | int b = 0; 102 | for( b = 0; b < MAX_BUFFERS; b++ ) 103 | { 104 | if( bufferinuse[b] == 0 ) break; 105 | } 106 | if( b == MAX_BUFFERS ) return; 107 | 108 | uint8_t * buffout = buffers[b]; 109 | ets_memcpy( buffout, r, 6 ); //Header 110 | ets_memcpy( buffout + 6, ((uint8_t*)r)+22, 6 ); //MAC From 111 | ets_memcpy( buffout + 12, mypacket+10, 6 ); //My MAC 112 | ets_memcpy( buffout + 18, ((uint8_t*)r)+42, 20 ); //ESPEED? 113 | //Two bytes at end of buffer are reserved. 114 | 115 | bufferinuse[b] = 1; 116 | 117 | // buffout[36] = debugccount>>24; 118 | // buffout[37] = debugccount>>16; 119 | // buffout[38] = debugccount>>8; 120 | // buffout[39] = debugccount>>0; No longer needed, put in place by interrupt. 121 | 122 | // espconn_sent(pUdpServer, buffout, 40 ); //+8 = include header 123 | 124 | 125 | //Tricky: Can't call espconn_sent from inside here. 126 | } 127 | 128 | 129 | static void ClearOutBuffers() 130 | { 131 | uint8_t sendbuffer[ MAX_BUFFERS * BUFFERSIZE ]; 132 | uint8_t * bpl = sendbuffer; 133 | int b = 0; 134 | for( b = 0; b < MAX_BUFFERS; b++ ) 135 | { 136 | if( !bufferinuse[b] ) continue; 137 | ets_memcpy( bpl, buffers[b], BUFFERSIZE ); 138 | bpl += BUFFERSIZE; 139 | bufferinuse[b] = 0; 140 | } 141 | espconn_sent(pUdpServer, sendbuffer, bpl-sendbuffer ); 142 | } 143 | 144 | int txpakid; 145 | 146 | void sent_freedom_cb(uint8 status) 147 | { 148 | /* 149 | int b = 0; 150 | for( b = 0; b < MAX_BUFFERS; b++ ) 151 | { 152 | if( bufferinuse[b] == 0 ) break; 153 | } 154 | if( b == MAX_BUFFERS ) return; 155 | */ 156 | debugccount2++; 157 | if( !packet_tx_time ) 158 | { 159 | return; 160 | } 161 | int b = MAX_BUFFERS-1; 162 | bufferinuse[b] = 1; 163 | 164 | uint8_t * buffout = buffers[b]; 165 | ets_memcpy( buffout, "\x00\x00\x00\x00\x00\x00", 6 ); //Header 166 | ets_memcpy( buffout + 6, mypacket+10, 6 ); //MAC From (us) 167 | ets_memcpy( buffout + 12, mypacket+10, 6 ); //My MAC (us) 168 | ets_memcpy( buffout + 18, "ESPTXX", 6 ); //ESPTXX 169 | 170 | buffout[24] = txpakid>>24; 171 | buffout[25] = txpakid>>16; 172 | buffout[26] = txpakid>>8; 173 | buffout[27] = txpakid>>0; 174 | 175 | buffout[28] = packet_tx_time>>0; 176 | buffout[29] = packet_tx_time>>8; 177 | buffout[30] = packet_tx_time>>16; 178 | buffout[31] = packet_tx_time>>24; 179 | packet_tx_time = 0; 180 | } 181 | 182 | 183 | //Timer event. 184 | extern uint8_t printed_ip; 185 | extern uint8_t * wDevCtrl; 186 | 187 | void PreEmpt_NMI_Vector(); 188 | static void ICACHE_FLASH_ATTR myTimer(void *arg) 189 | { 190 | static int thistik; 191 | static int waittik; 192 | thistik++; 193 | 194 | CSTick( 0 ); 195 | printf( "!!%d\n", debugccount3 ); 196 | // wifi_set_user_fixed_rate( 3, 0x0b ); //0xb = 6Mbit G 197 | // wifi_set_user_fixed_rate( 3, 0x0c ); //0xc = 54Mbit G 198 | // wifi_set_user_fixed_rate( 3, 0x07 ); //0x7 = 11Mbit ... B? 199 | 200 | //0x02 = 5.5Mbit/s (B) 201 | //0x01 = 2Mbit/s (B) 202 | //0x00 = 1Mbit/s (B) 203 | //0x10 = 6.5MBit 204 | //0x11 = 13MBit 205 | //0x1f = 72.2Mbit/s 206 | // wifi_set_phy_mode(PHY_MODE_11N); 207 | 208 | //54 mbit 209 | // wifi_set_phy_mode(PHY_MODE_11G); //??? Maybe - I haven't been doing this... 210 | // wifi_set_user_fixed_rate( 3, 0x0c ); 211 | 212 | 213 | wifi_set_phy_mode(PHY_MODE_11N); //??? Maybe - I haven't been doing this... 214 | wifi_set_user_fixed_rate( 3, 0x1f ); 215 | 216 | // wifi_set_user_limit_rate_mask( 3 ); 217 | // wifi_set_user_rate_limit( FIXED_RATE_MASK_ALL, 0, 1, 1 ); 218 | 219 | if( thistik == waittik-3 ) 220 | { 221 | int i; 222 | static int did_init = 0; 223 | 224 | if( !did_init && printed_ip ) 225 | { 226 | //For sending raw packets. 227 | //SetupRawsend(); 228 | wifi_set_raw_recv_cb( rx_func ); 229 | 230 | wifi_register_send_pkt_freedom_cb( sent_freedom_cb ); 231 | 232 | did_init = 1; 233 | 234 | //Setup our send packet with our MAC address. 235 | wifi_get_macaddr(STATION_IF, mypacket + 10); 236 | debugccount = 0; 237 | 238 | //printf( "!!!\n" ); 239 | } 240 | 241 | 242 | //printf( "%d\n", debugccount ); 243 | //uart0_sendStr("k"); 244 | ets_strcpy( mypacket+30, "ESPEED" ); 245 | txpakid++; 246 | mypacket[36] = txpakid>>24; 247 | mypacket[37] = txpakid>>16; 248 | mypacket[38] = txpakid>>8; 249 | mypacket[39] = txpakid>>0; 250 | mypacket[40] = 0; 251 | mypacket[41] = 0; 252 | mypacket[42] = 0; 253 | mypacket[43] = 0; 254 | 255 | packet_tx_time = 0; 256 | wifi_send_pkt_freedom( mypacket, 30 + 16, true) ; 257 | //Looks like we can actually set the speed --> wifi_set_user_fixed_rate( 3, 12 ); 258 | } 259 | else if( thistik >= waittik ) //Happens 3ms later. 260 | { 261 | ClearOutBuffers(); 262 | 263 | CSTick( 1 ); 264 | 265 | thistik = 0; 266 | waittik = rand()%10 + 40; 267 | } 268 | } 269 | 270 | void ICACHE_FLASH_ATTR charrx( uint8_t c ) {/*Called from UART.*/} 271 | 272 | void user_init(void) 273 | { 274 | uart_init(BIT_RATE_115200, BIT_RATE_115200); 275 | uart_init(BIT_RATE_115200, BIT_RATE_115200); 276 | 277 | debugcontrol = 0xffffffff; 278 | 279 | system_update_cpu_freq(160); 280 | 281 | uart0_sendStr("testing...\r\n\033ctesting" ); //Clear screen 282 | uart0_sendStr("\r\nesp82XX Web-GUI\r\n" VERSSTR "\b"); 283 | 284 | 285 | struct rst_info * r = system_get_rst_info(); 286 | printf( "Reason: %p\n", r->reason ); 287 | printf( "Exec : %p\n", r->exccause ); 288 | printf( "epc1 : %p\n", r->epc1 ); 289 | printf( "epc2 : %p\n", r->epc2 ); 290 | printf( "epc3 : %p\n", r->epc3 ); 291 | printf( "excvaddr:%p\n", r->excvaddr ); 292 | printf( "depc: %p\n", r->depc ); 293 | 294 | 295 | 296 | CSSettingsLoad( 0 ); 297 | CSPreInit(); 298 | 299 | CSInit(); 300 | 301 | 302 | //Set GPIO16 for INput 303 | WRITE_PERI_REG(PAD_XPD_DCDC_CONF, 304 | (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | (uint32)0x1); // mux configuration for XPD_DCDC and rtc_gpio0 connection 305 | 306 | WRITE_PERI_REG(RTC_GPIO_CONF, 307 | (READ_PERI_REG(RTC_GPIO_CONF) & (uint32)0xfffffffe) | (uint32)0x0); //mux configuration for out enable 308 | 309 | WRITE_PERI_REG(RTC_GPIO_ENABLE, 310 | READ_PERI_REG(RTC_GPIO_ENABLE) & (uint32)0xfffffffe); //out disable 311 | 312 | SetServiceName( "ws2812" ); 313 | AddMDNSName( "esp82xx" ); 314 | AddMDNSName( "rawpack" ); 315 | AddMDNSService( "_http._tcp", "An ESP8266 Webserver", WEB_PORT ); 316 | AddMDNSService( "_esp82xx._udp", "ESP8266 Backend", BACKEND_PORT ); 317 | 318 | 319 | pUdpServer = (struct espconn *)os_zalloc(sizeof(struct espconn)); 320 | ets_memset( pUdpServer, 0, sizeof( struct espconn ) ); 321 | espconn_create( pUdpServer ); 322 | pUdpServer->type = ESPCONN_UDP; 323 | pUdpServer->proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp)); 324 | pUdpServer->proto.udp->local_port = 9999; 325 | pUdpServer->proto.udp->remote_port = 9999; 326 | pUdpServer->proto.udp->remote_ip[0] = 192; 327 | pUdpServer->proto.udp->remote_ip[1] = 168; 328 | pUdpServer->proto.udp->remote_ip[2] = 1; 329 | pUdpServer->proto.udp->remote_ip[3] = 113; 330 | espconn_regist_recvcb(pUdpServer, udpserver_recv); 331 | if( espconn_create( pUdpServer ) ) 332 | while(1) 333 | uart0_sendStr( "\r\nFAULT\r\n" ); 334 | 335 | 336 | //XXX TODO figure out how to safely re-allow this. 337 | 338 | //Add a process 339 | system_os_task(procTask, procTaskPrio, procTaskQueue, procTaskQueueLen); 340 | 341 | uart0_sendStr("\r\nCustom Server\r\n"); 342 | 343 | //Timer example 344 | os_timer_disarm(&some_timer); 345 | os_timer_setfn(&some_timer, (os_timer_func_t *)myTimer, NULL); 346 | os_timer_arm(&some_timer, 1, 1); //The underlying API expects it's slow ticks to average out to 50ms. 347 | 348 | //system_os_post(procTaskPrio, 0, 0 ); 349 | 350 | PIN_DIR_OUTPUT = _BV(2); 351 | PIN_OUT_SET = _BV(2); 352 | PIN_OUT_CLEAR = _BV(2); 353 | } 354 | 355 | //There is no code in this project that will cause reboots if interrupts are disabled. 356 | void EnterCritical() {} 357 | void ExitCritical() {} 358 | 359 | uint32 ICACHE_FLASH_ATTR 360 | user_rf_cal_sector_set(void) 361 | { 362 | enum flash_size_map size_map = system_get_flash_size_map(); 363 | uint32 rf_cal_sec = 0; 364 | 365 | switch (size_map) { 366 | case FLASH_SIZE_4M_MAP_256_256: 367 | rf_cal_sec = 128 - 8; 368 | break; 369 | 370 | case FLASH_SIZE_8M_MAP_512_512: 371 | rf_cal_sec = 256 - 5; 372 | break; 373 | 374 | case FLASH_SIZE_16M_MAP_512_512: 375 | case FLASH_SIZE_16M_MAP_1024_1024: 376 | rf_cal_sec = 512 - 5; 377 | break; 378 | 379 | case FLASH_SIZE_32M_MAP_512_512: 380 | case FLASH_SIZE_32M_MAP_1024_1024: 381 | rf_cal_sec = 1024 - 5; 382 | break; 383 | 384 | default: 385 | rf_cal_sec = 0; 386 | break; 387 | } 388 | 389 | return rf_cal_sec; 390 | } 391 | -------------------------------------------------------------------------------- /toprecorder/process.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | using namespace std; 12 | 13 | #define NRNODES 5 14 | 15 | struct DataEntry 16 | { 17 | string IP; 18 | int rssi; 19 | string macFrom; 20 | string macTo; 21 | uint32_t pid; 22 | uint32_t time; 23 | }; 24 | 25 | vector< DataEntry > Entries; 26 | 27 | class Node; 28 | 29 | Node * NODES[NRNODES]; 30 | 31 | 32 | void LoadEntries( const char * filename ); 33 | int gFrame; 34 | int still_init = 0; 35 | const double MHz = 160; //160; 36 | const double SoL = 299792458; 37 | double CalculateToF( string Mac1, string Mac2 ); //In 1/MHz 38 | int GetNodeId( string mac ); 39 | 40 | 41 | /* NODES[0] = new Node( "5ccf7fc0c75c", 1, 0, 0, 0, 0); //.147 42 | NODES[1] = new Node( "5ccf7fc0d218", 1, DistanceMeters168, 0, 0, 1 ); //.179 43 | NODES[2] = new Node( "5ccf7fc10b08", 1, 0, DistanceMeters162, 0, 2 ); //.169 44 | NODES[3] = new Node( "5ccf7fc06055", 1, DistanceMeters168, DistanceMeters162, 0, 3 ); //.241 45 | */ 46 | 47 | #define KNOWN_NODE_3 1 48 | 49 | #if 1 50 | double ToFMatrix[5][5] = { 51 | 0, 2.2, 2.2, 3.17, 1.5, 52 | 2.2, 0, 3.17, 2.2, 1.5, 53 | 2.2, 3.17, 0, 2.2, 1.5, 54 | 3.17, 2.2, 2.2, 0, 1.5, 55 | 1.5, 1.5, 1.5, 1.5, 0 }; 56 | #else 57 | #if 0 58 | double ToFMatrix[5][5] = { 59 | 0, 2.2, 2.2, 3.17, 60 | 2.2, 0, 3.17, 2.2, 61 | 2.2, 3.17, 0, 2.2, 62 | 3.17, 2.2, 2.2, 0, 63 | }; 64 | #else 65 | double ToFMatrix[5][5] = { 66 | 0, 0, 0, 0, 67 | 0, 0, 0, 0, 68 | 0, 0, 0, 0, 69 | 0, 0, 0, 0, 70 | }; 71 | #endif 72 | #endif 73 | 74 | //#define NR_ITERATIONS 10000 75 | #define NR_ITERATIONS 1 76 | #define INIT_FRAMES 2000 77 | #define START_CULL 7000 78 | #define DETAIL_DEBUG 79 | 80 | #ifdef DETAIL_DEBUG 81 | #undef NR_ITERATIONS 82 | #define NR_ITERATIONS 1 83 | #endif 84 | 85 | static const double syncoff = 0.001; //The factor by which to correct off-sync-ness 86 | static const double syncslew = 0.0000002; //The factor by which to correct slew offsets 87 | static const double syncslewD = 0.00001; 88 | 89 | static const double syncoff_before = 0.1; //The factor by which to correct off-sync-ness 90 | static const double syncslew_before = 0.0000001; //The factor by which to correct slew offsets 91 | 92 | 93 | class Node 94 | { 95 | public: 96 | 97 | Node() : myMac(""), is_known(false), x(0), y(0), z(0), nodeid(-1), currentpid(-1), VirtualTimeOffset(0), DeltaTFilt(0), LastDeltaTFilt(0), got_time(0), last_time(0), running_time(0) { 98 | memset( GotPeerTime, 0, sizeof( GotPeerTime ) ); memset( PeerTime, 0, sizeof( PeerTime ) ); memset( othernodedeltas, 0, sizeof( othernodedeltas ) ); memset( othernodedeltascount, 0, sizeof(othernodedeltascount) ); memset( LastDelta, 0, sizeof( LastDelta ) ); 99 | } 100 | 101 | Node( string mac, int ik, double tx, double ty, double tz, int nid ) : myMac( mac ), is_known(ik), x(tx), y(ty), z(tz), nodeid(nid), VirtualTimeOffset(0), DeltaTFilt(0), LastDeltaTFilt(0), got_time(0), last_time(0), running_time(0) { 102 | memset( GotPeerTime, 0, sizeof( GotPeerTime ) ); memset( PeerTime, 0, sizeof( PeerTime ) ); memset( othernodedeltas, 0, sizeof( othernodedeltas ) ); memset( othernodedeltascount, 0, sizeof(othernodedeltascount) ); memset( LastDelta, 0, sizeof( LastDelta ) ); 103 | } 104 | 105 | string myMac; 106 | int is_known; //Is the ToFs of this node known? 107 | double x; 108 | double y; 109 | double z; 110 | 111 | int nodeid; 112 | int currentpid; 113 | 114 | bool GotPeerTime[NRNODES]; 115 | double PeerTime[NRNODES]; 116 | double LastDelta[NRNODES]; 117 | 118 | //Tricky: This is the time sync values (will be set by sender on receiver) 119 | double VirtualTimeOffset; 120 | double DeltaTFilt; 121 | double LastDeltaTFilt; 122 | 123 | //These three are just for parsing times, nothing tricky. 124 | double running_time; 125 | double clockskewratio; 126 | uint32_t last_time; 127 | bool got_time; 128 | 129 | int othernodedeltascount[NRNODES]; 130 | double othernodedeltas[NRNODES]; 131 | 132 | //Called by transmitters. Once per 133 | void SyncTimes( int nodeto ) 134 | { 135 | int i, j; 136 | // if( is_known ) 137 | { 138 | for( i = 0; i < NRNODES; i++ ) 139 | { 140 | if( nodeto == i ) continue; 141 | 142 | if( GotPeerTime[i] ) 143 | { 144 | double delta = PeerTime[nodeto] - PeerTime[i]; 145 | //LastDelta[i] = delta; 146 | 147 | //printf( "%f - %f = %f\n", PeerTime[nodeto], PeerTime[i], delta ); 148 | if( still_init ) 149 | { 150 | if( delta < -100000 ) delta = -100000; 151 | if( delta > 100000 ) delta = 100000; 152 | } 153 | else 154 | { 155 | //fprintf( stderr, "%f", delta ); 156 | 157 | 158 | //If the delta is unacceptable (60 seems good) that means we got a wrong timestamp. Throw it out. 159 | if( gFrame > START_CULL*2 ) 160 | { 161 | if( delta < -8 ) continue; //delta = -20; 162 | if( delta > 8 ) continue; //delta = 20; 163 | NODES[i]->LastDelta[nodeto] = delta; 164 | NODES[nodeto]->LastDelta[i] = -delta; 165 | } 166 | else if( gFrame > START_CULL ) 167 | { 168 | if( delta < -50 ) continue; //delta = -20; 169 | if( delta > 50 ) continue; //delta = 20; 170 | //fprintf( stderr, "\n", delta ); 171 | NODES[i]->LastDelta[nodeto] = delta; 172 | NODES[nodeto]->LastDelta[i] = -delta; 173 | } 174 | 175 | 176 | } 177 | 178 | if( gFrame > START_CULL ) 179 | { 180 | othernodedeltas[nodeto] += delta; 181 | othernodedeltascount[nodeto]++; 182 | othernodedeltas[i] += -delta; 183 | othernodedeltascount[i]++; 184 | //printf( "%d / %d / %d\n", nodeid, othernode, othernodedeltascount[othernode] ); 185 | } 186 | 187 | 188 | if( NODES[nodeto]->is_known ) 189 | { 190 | NODES[i]->UpdateVirtualTime( delta, nodeto ); 191 | } 192 | if( NODES[i]->is_known ) 193 | { 194 | NODES[nodeto]->UpdateVirtualTime( -delta, i ); 195 | } 196 | } 197 | } 198 | 199 | #ifdef DETAIL_DEBUG 200 | //if( !still_init ) 201 | { 202 | for( i = 0; i < NRNODES; i++ ) 203 | { 204 | printf( "%f, %f, %f, %f, %f, %f, %f, ", NODES[i]->VirtualTimeOffset, (NODES[i]->clockskewratio-1.0)*1000000, NODES[i]->LastDelta[0], NODES[i]->LastDelta[1], NODES[i]->LastDelta[2], NODES[i]->LastDelta[3], NODES[i]->LastDelta[4] ); 205 | // printf( "%f ", NODES[i]->VirtualTimeOffset ); 206 | } 207 | printf( "%d\n", still_init ); 208 | } 209 | #endif 210 | } 211 | } 212 | 213 | void UpdateVirtualTime( double delta, int othernode ) 214 | { 215 | if( still_init ) 216 | delta = delta * syncoff_before; 217 | else 218 | delta = delta * syncoff; 219 | 220 | double tsync = syncslew; 221 | if( still_init ) tsync = syncslew_before; 222 | 223 | double clockskewoff = tsync * delta; 224 | if( clockskewoff > tsync ) clockskewoff = tsync; 225 | if( clockskewoff <-tsync ) clockskewoff =-tsync; 226 | clockskewratio += clockskewoff; 227 | VirtualTimeOffset += delta; 228 | 229 | DeltaTFilt = DeltaTFilt * .99 + delta * .1; 230 | 231 | clockskewratio += syncslewD * -(LastDeltaTFilt-DeltaTFilt); 232 | 233 | LastDeltaTFilt = DeltaTFilt; 234 | } 235 | 236 | void ResetPeerTimes() 237 | { 238 | for( int i = 0; i < NRNODES; i++ ) 239 | { 240 | GotPeerTime[i] = 0; 241 | PeerTime[i] = 0; 242 | } 243 | } 244 | 245 | //This is called when a foreign object received one of our packets. 246 | void TransmittedMessage( int nodeto, double RealTime, int pid ) 247 | { 248 | if( nodeto < 0 ) return; 249 | 250 | if( pid != currentpid ) 251 | { 252 | //Clear out adjacency properties. 253 | currentpid = pid; 254 | ResetPeerTimes(); 255 | } 256 | 257 | GotPeerTime[nodeto] = 1; 258 | PeerTime[nodeto] = (RealTime - GetToF( *NODES[nodeto] )); 259 | SyncTimes( nodeto ); 260 | } 261 | 262 | double GetToF( Node & other ) ///TOF TOF TOF 263 | { 264 | if ( !is_known || !other.is_known ) return 0; 265 | //return ToFMatrix[nodeid][other.nodeid]*1.0; 266 | double dx = x - other.x; 267 | double dy = y - other.y; 268 | double dz = z - other.z; 269 | double dist = sqrtf( dx*dx+dy*dy+dz*dz ); 270 | double dt = dist / SoL * (MHz * 1000000); 271 | return dt; 272 | 273 | } 274 | 275 | double RxTimeToReal( uint32_t rxtime ) //In ticks. 276 | { 277 | if( !got_time ) 278 | { 279 | got_time = true; 280 | last_time = rxtime; 281 | running_time = 0; 282 | clockskewratio = 1.0; 283 | return 0; 284 | } 285 | 286 | uint32_t rxdtime = rxtime - last_time; 287 | last_time = rxtime; 288 | running_time += rxdtime * clockskewratio; 289 | return running_time + VirtualTimeOffset; //In ticks 290 | } 291 | }; 292 | 293 | 294 | void ProcessEntries() 295 | { 296 | int i; 297 | 298 | for( i = 0; i < Entries.size(); i++ ) 299 | { 300 | DataEntry & e = Entries[i]; 301 | //192.168.11.169/44/5ccf7fc0c75c/5ccf7fc10b08/18079/2194663737 302 | //printf ("%s/%d/%s/%s/%u/%u\n", e.IP.c_str(), e.rssi, e.macFrom.c_str(), e.macTo.c_str(), e.pid, e.time ); 303 | 304 | if( e.time == 0 ) continue; 305 | 306 | gFrame = i; 307 | still_init = i < INIT_FRAMES; //If still init, update clocks very quickly. 308 | int nfrom = GetNodeId( e.macFrom ); 309 | int nto = GetNodeId( e.macTo ); 310 | 311 | if( nto >= 0 && nfrom >= 0 ) 312 | { 313 | double LoopTime = NODES[nto]->RxTimeToReal( e.time ); 314 | NODES[nfrom]->TransmittedMessage( nto, LoopTime, e.pid ); 315 | } 316 | } 317 | 318 | /* 319 | double SlaveTimeDeltas[3]; 320 | double SlaveTimeDeltasTemp[3]; 321 | int GotNodesTemp[3]; 322 | int CurSyncId; 323 | 324 | double slews[2]; 325 | int firstslew = 0; 326 | 327 | for( i = 0; i < Entries.size(); i++ ) 328 | { 329 | DataEntry & e = Entries[i]; 330 | //192.168.11.169/44/5ccf7fc0c75c/5ccf7fc10b08/18079/2194663737 331 | double tof = CalculateToF( e.macFrom, e.macTo ); 332 | //printf ("%s/%d/%s/%s/%u/%u/%f\n", e.IP.c_str(), e.rssi, e.macFrom.c_str(), e.macTo.c_str(), e.pid, e.time, tof ); 333 | 334 | int nodeto = GetNodeId( e.macTo ) - 1; 335 | if( e.pid != CurSyncId ) 336 | { 337 | CurSyncId = e.pid; 338 | GotNodesTemp[0] = GotNodesTemp[1] = GotNodesTemp[2] = 0; 339 | } 340 | 341 | if( e.macFrom == MasterMac ) 342 | { 343 | double sendtime = e.time - tof; 344 | SlaveTimeDeltasTemp[nodeto] = sendtime; 345 | GotNodesTemp[nodeto] = 1; 346 | if( GotNodesTemp[0] && GotNodesTemp[1] && GotNodesTemp[2] ) 347 | { 348 | SlaveTimeDeltas[0] = SlaveTimeDeltasTemp[0]; 349 | SlaveTimeDeltas[1] = SlaveTimeDeltasTemp[1]; 350 | SlaveTimeDeltas[2] = SlaveTimeDeltasTemp[2]; 351 | uint32_t slew1 = SlaveTimeDeltas[0] - SlaveTimeDeltasTemp[2]; 352 | uint32_t slew2 = SlaveTimeDeltas[1] - SlaveTimeDeltasTemp[2]; 353 | if( firstslew == 0 ) 354 | { 355 | firstslew = 1; 356 | slews[0] = slew1; 357 | slews[1] = slew2; 358 | } 359 | printf( "%f %f\n", slew1 - slews[0], slew2 - slews[1] ); 360 | } 361 | } 362 | }*/ 363 | } 364 | 365 | 366 | int main( int argc, char ** argv ) 367 | { 368 | if( argc != 2 ) 369 | { 370 | fprintf( stderr, "Error: Usage: [tool] [data file]\n" ); 371 | return -5; 372 | } 373 | 374 | 375 | //192.168.11.169 27102e400000 5ccf7fc06055 5ccf7fc10b08 ESPEEDEE 17879 4255185525 376 | LoadEntries( argv[1] ); 377 | 378 | 379 | double BackupToFMatrix[5][5]; 380 | double backupError = 1e20; 381 | double anneal = 1.0; 382 | memcpy(BackupToFMatrix, ToFMatrix, sizeof( ToFMatrix ) ); 383 | 384 | srand(5); 385 | int k; 386 | for (k = 0; k < NR_ITERATIONS; k++) 387 | { 388 | 389 | if( NR_ITERATIONS > 1 ) 390 | { 391 | memcpy( ToFMatrix, BackupToFMatrix, sizeof( ToFMatrix ) ); 392 | int xcellmod = rand()%(NRNODES); 393 | int ycellmod = rand()%(NRNODES-1); 394 | if( ycellmod >= xcellmod ) ycellmod++; 395 | //ToFMatrix[xcellmod][ycellmod] += (rand()%10000-5000)/5000.0*anneal; 396 | double emt = (rand()%10000-5000)/5000.0*anneal; 397 | ToFMatrix[xcellmod][ycellmod] += emt; 398 | ToFMatrix[ycellmod][xcellmod] += emt; 399 | 400 | xcellmod = rand()%NRNODES; 401 | ycellmod = rand()%(NRNODES-1); 402 | if( ycellmod >= xcellmod ) ycellmod++; 403 | emt = (rand()%10000-5000)/5000.0*anneal; 404 | //ToFMatrix[xcellmod][ycellmod] += (rand()%10000-5000)/5000.0*anneal; 405 | ToFMatrix[xcellmod][ycellmod] += emt; 406 | ToFMatrix[ycellmod][xcellmod] += emt; 407 | } 408 | 409 | anneal *= 0.9995; 410 | //ToFMatrix[ycellmod][xcellmod] += (rand()%10000)/10000.0; 411 | 412 | int i; 413 | for( i = 0; i < NRNODES; i++ ) 414 | if( NODES[i] ) delete NODES[i]; 415 | 416 | double DistanceMeters162 = -4.1148*1.0; 417 | double DistanceMeters168 = 4.2672*1.0; 418 | 419 | #define DO_SPACING 420 | 421 | /* 422 | #ifdef DO_SPACING 423 | NODES[0] = new Node( "5ccf7fc0c75c", 1, 0, 0, 0, 0); //.147 424 | NODES[1] = new Node( "5ccf7fc0d218", 1, DistanceMeters168, DistanceMeters162, 0, 1 ); //.179 425 | NODES[2] = new Node( "5ccf7fc10b08", 1, 0, DistanceMeters162, 0, 2 ); //.169(167) 426 | NODES[3] = new Node( "5ccf7fc06055", KNOWN_NODE_3, DistanceMeters168, 0, 0, 3 ); //.241 427 | #if NRNODES>4 428 | NODES[4] = new Node( "5ccf7fc10aff", 1, DistanceMeters168/2, DistanceMeters162/2, 0, 3 ); //.214 429 | #endif 430 | 431 | #else 432 | NODES[0] = new Node( "5ccf7fc0c75c", 1, 0, 0, 0, 0); //.147 433 | NODES[1] = new Node( "5ccf7fc0d218", 1, 0, 0, 0, 1 ); //.179 434 | NODES[2] = new Node( "5ccf7fc10b08", 1, 0, 0, 0, 2 ); //.169 435 | NODES[3] = new Node( "5ccf7fc06055", 1, 0, 0, 0, 3 ); //.241 436 | #if NRNODES>4 437 | NODES[4] = new Node( "5ccf7fc10aff", 0, 0, 0, 0, 3 ); //.214 438 | #endif 439 | 440 | #endif 441 | */ 442 | /* 443 | 444 | 214 445 | 10' 446 | === 447 | 241 ------- 25' -------- 147 448 | -- 449 | 25' 450 | -- 451 | 179 -------- 25' 169 452 | */ 453 | double m25 = 7.62/10; 454 | double m10 = 3.048/10; 455 | 456 | 457 | NODES[0] = new Node( "5ccf7fc0c75c", 1, m25, 0, 0, 0 ); //.147 458 | NODES[1] = new Node( "5ccf7fc0d218", 1, 0, m25, 0, 1 ); //.179 459 | NODES[2] = new Node( "5ccf7fc10b08", 1, m25, m25, 0, 2 ); //.169 460 | NODES[3] = new Node( "5ccf7fc06055", 1, 0, 0, 0, 3 ); //.241 461 | NODES[4] = new Node( "5ccf7fc10aff", 1, m25/2, -m10, 0, 3 ); //.214(213) 462 | 463 | 464 | 465 | /* 466 | 147 -- 168 in -- 179 467 | | 468 | | 469 | 162 in 470 | | 471 | | 472 | 167 ------------ 241 473 | */ 474 | 475 | 476 | 477 | ProcessEntries(); 478 | 479 | 480 | // printf( "Term %d\n", Entries.size() ); 481 | 482 | double totalerror = 0.0; 483 | for( int i = 0; i < NRNODES; i++ ) 484 | { 485 | for( int j = 0; j < NRNODES; j++ ) 486 | { 487 | printf( "%d->%d -> %f (%d entries)\n", i, j, NODES[i]->othernodedeltas[j]/NODES[i]->othernodedeltascount[j], NODES[i]->othernodedeltascount[j] ); 488 | double err = NODES[i]->othernodedeltas[j]/NODES[i]->othernodedeltascount[j]; 489 | if( NODES[i]->othernodedeltascount[j] ) 490 | totalerror += fabs( err ); 491 | } 492 | printf( "\n" ); 493 | } 494 | 495 | if( totalerror < backupError ) 496 | { 497 | memcpy( BackupToFMatrix, ToFMatrix, sizeof( ToFMatrix ) ); 498 | backupError = totalerror; 499 | } 500 | 501 | for( int i = 0; i < NRNODES; i++ ) 502 | { 503 | for( int j = 0; j < NRNODES; j++ ) 504 | { 505 | printf( "%f ", ToFMatrix[i][j] ); 506 | } 507 | printf( "\n" ); 508 | } 509 | fprintf( stderr, "%f Best: %f Anneal: %f\n", totalerror, backupError, anneal ); 510 | 511 | } 512 | 513 | 514 | return 0; 515 | } 516 | 517 | 518 | 519 | 520 | void LoadEntries( const char * filename ) 521 | { 522 | FILE * f = fopen( filename, "r" ); 523 | if( !f ) 524 | { 525 | fprintf( stderr, "Error: Could not open file \"%s\" for loading\n", filename ); 526 | exit( -5 ); 527 | } 528 | 529 | char *line = NULL; 530 | size_t len = 0; 531 | ssize_t read; 532 | int lineno = 0; 533 | 534 | 535 | 536 | while ((read = getline(&line, &len, f)) != -1) { 537 | char ip[32]; 538 | unsigned long long param1; 539 | char macf[32]; 540 | char mact[32]; 541 | char code[32]; 542 | uint32_t pid; 543 | uint32_t time; 544 | 545 | lineno++; 546 | int r = sscanf( line, "%31s %llx %31s %31s %31s %u %u", ip, ¶m1, macf, mact, code, &pid, &time ); 547 | if( r != 7 ) 548 | { 549 | fprintf( stderr, "Error reading line %d, got %d params\n", lineno, r ); 550 | continue; 551 | } 552 | 553 | if( strcmp( code, "ESPEED" ) != 0 ) 554 | { 555 | //fprintf( stderr, "Error: unmatching code on line %d\n", lineno ); 556 | continue; 557 | } 558 | DataEntry e; 559 | e.IP = ip; 560 | e.rssi = param1>>40; 561 | e.macFrom = macf; 562 | e.macTo = mact; 563 | e.pid = pid; 564 | e.time = time; 565 | Entries.push_back( e ); 566 | } 567 | 568 | fclose( f ); 569 | } 570 | 571 | int GetNodeId( string mac ) { 572 | int i; for( i = 0; i < NRNODES; i++ ) if( mac == NODES[i]->myMac ) return i; 573 | static map< string, int > showns; 574 | if( showns[mac.c_str()] == 0 ) 575 | { 576 | fprintf( stderr, "Error: can't find node %s\n", mac.c_str() ); 577 | showns[mac.c_str()] = 1; 578 | } 579 | return -1; 580 | } 581 | 582 | -------------------------------------------------------------------------------- /web/page/menuinterface.js: -------------------------------------------------------------------------------- 1 | //Copyright (C) 2015 <>< Charles Lohr, see LICENSE file for more info. 2 | // 3 | //This particular file may be licensed under the MIT/x11, New BSD or ColorChord Licenses. 4 | var wsUri = "ws://" + location.host + "/d/ws/issue"; 5 | var output; 6 | var websocket; 7 | var commsup = 0; 8 | 9 | var mpfs_start_at = 65536; //1048576; NOTE: If you select 1048576, it will override the 65536 sector, but has much more room. 10 | var flash_scratchpad_at = 524288; 11 | var flash_blocksize = 65536; 12 | var flash_sendsize = 256; 13 | //Push objects that have: 14 | // .request 15 | // .callback = function( ref (this object), data ); 16 | 17 | var workqueue = []; 18 | var wifilines = []; 19 | var workarray = {}; 20 | var lastitem; 21 | 22 | var SystemMessageTimeout = null; 23 | function IssueSystemMessage( msg ) 24 | { 25 | var elem = $( "#SystemMessage" ); 26 | elem.hide(); 27 | elem.html( "" + msg + "" ); 28 | elem.slideToggle( 'fast' ); 29 | if( SystemMessageTimeout != null ) clearTimeout(SystemMessageTimeout); 30 | SystemMessageTimeout = setTimeout( function() { SystemMessageTimeout = null; $( "#SystemMessage" ).fadeOut( 'slow' ) }, 3000 ); 31 | } 32 | 33 | function QueueOperation( command, callback, extra ) 34 | { 35 | if( workarray[command] == 1 ) 36 | { 37 | return; 38 | } 39 | 40 | workarray[command] = 1; 41 | var vp = new Object(); 42 | vp.callback = callback; 43 | vp.extra = extra; 44 | vp.request = command; 45 | workqueue.push( vp ); 46 | } 47 | 48 | 49 | function init() 50 | { 51 | GPIOlines = ''; 52 | for(var i=0; i<16; ++i) 53 | GPIOlines += ""+ i 54 | + "" 55 | + "" 56 | + ""; 57 | 58 | $('#MainMenu > tbody:first-child').before( "\ 59 | \ 60 | \ 61 |
\ 62 |
\ 63 |
\n
" 64 | ); 65 | 66 | $('#MainMenu > tbody:last-child').after( "\ 67 | \ 68 | \ 69 |
\ 70 |
\ 71 | Current Configuration: (May deviate from default configuration, reset here if in doubt)
\ 72 | \ 73 | \ 74 | \ 75 | \ 76 | \ 77 | \ 78 | \ 79 |
Type:Station (Connect to infrastructure)
AP (Broadcast a new AP)
SSID:
PASS:
MAC: (Ignored in softAP mode)
Chan: (Ignored in Station mode)
(Automatically saves to flash)
\ 80 | Scanned Stations: \ 81 |
\ 82 | \ 83 |
\ 84 | \ 85 | \ 86 | \ 87 |
\ 88 |
\ 89 | Command: \ 90 |
\ 91 | \ 92 |
\ 93 | \ 94 | \ 95 | \ 96 |
\ 97 | " + 98 | GPIOlines 99 | + "
\ 100 | \ 101 | \ 102 | \ 103 |
\ 104 |
\ 105 |
Drop or browse for system (0x000.. 0x400...) or web (.mpfs) reflash files.
\ 106 |
" 107 | ); 108 | 109 | MakeDragDrop( "InnerSystemReflash", DragDropSystemFiles ); 110 | $("#dragndropersystem").change(function() { DragDropSystemFiles(this.files ); }); 111 | 112 | $( ".collapsible" ).each(function( index ) { 113 | if( localStorage["sh" + this.id] > 0.5 ) 114 | { 115 | $( this ).show().toggleClass( 'opened' ); 116 | // console.log( "OPEN: " + this.id ); 117 | } 118 | }); 119 | 120 | $("#custom_command_response").val( "" ); 121 | 122 | //Preclude drag and drop on rest of document in event user misses firmware boxes. 123 | donothing = function(e) {e.stopPropagation();e.preventDefault();}; 124 | $(document).on('drop', donothing ); 125 | $(document).on('dragover', donothing ); 126 | $(document).on('dragenter', donothing ); 127 | 128 | output = document.getElementById("output"); 129 | 130 | KickWifiTicker(); 131 | GPIODataTickerStart(); 132 | InitSystemTicker(); 133 | 134 | console.log( "Load complete.\n" ); 135 | Ticker(); 136 | } 137 | 138 | window.addEventListener("load", init, false); 139 | 140 | 141 | function StartWebSocket() 142 | { 143 | output.innerHTML = "Connecting..."; 144 | if( websocket ) websocket.close(); 145 | workarray = {}; 146 | workqueue = []; 147 | lastitem = null; 148 | websocket = new WebSocket(wsUri); 149 | websocket.onopen = function(evt) { onOpen(evt) }; 150 | websocket.onclose = function(evt) { onClose(evt) }; 151 | websocket.onmessage = function(evt) { onMessage(evt) }; 152 | websocket.onerror = function(evt) { onError(evt) }; 153 | } 154 | 155 | function onOpen(evt) 156 | { 157 | doSend('e' ); 158 | } 159 | 160 | function onClose(evt) 161 | { 162 | $('#SystemStatusClicker').css("color", "red" ); 163 | commsup = 0; 164 | } 165 | 166 | var msg = 0; 167 | var tickmessage = 0; 168 | var lasthz = 0; 169 | var time_since_hz = 10; //Make it realize it was disconnected to begin with. 170 | 171 | function Ticker() 172 | { 173 | setTimeout( Ticker, 1000 ); 174 | 175 | lasthz = (msg - tickmessage); 176 | tickmessage = msg; 177 | if( lasthz == 0 ) 178 | { 179 | time_since_hz++; 180 | if( time_since_hz > 3 ) 181 | { 182 | $('#SystemStatusClicker').css("color", "red" ); 183 | $('#SystemStatusClicker').prop( "value", "System Offline" ); 184 | if( commsup != 0 && !is_waiting_on_stations ) IssueSystemMessage( "Comms Lost." ); 185 | commsup = 0; 186 | StartWebSocket(); 187 | } 188 | else 189 | $('#SystemStatusClicker').prop( "value", "System " + 0 + "Hz" ); 190 | } 191 | else 192 | { 193 | time_since_hz = 0; 194 | $('#SystemStatusClicker').prop( "value", "System " + lasthz + "Hz" ); 195 | } 196 | } 197 | 198 | 199 | function onMessage(evt) 200 | { 201 | msg++; 202 | 203 | 204 | if( commsup != 1 ) 205 | { 206 | commsup = 1; 207 | $('#SystemStatusClicker').css("color", "green" ); 208 | IssueSystemMessage( "Comms Established." ); 209 | } 210 | 211 | 212 | if( lastitem ) 213 | { 214 | if( lastitem.callback ) 215 | { 216 | lastitem.callback( lastitem, evt.data ); 217 | lastitem = null; 218 | } 219 | } 220 | else 221 | { 222 | if( evt.data.length > 2 ) 223 | { 224 | var wxresp = evt.data.substr(2).split("\t"); 225 | output.innerHTML = "

Messages: " + msg + "

RSSI: " + wxresp[0] + " / IP: " + ((wxresp.length>1)?HexToIP( wxresp[1] ):"") + "

"; 226 | } 227 | } 228 | 229 | 230 | if( workqueue.length ) 231 | { 232 | var elem = workqueue.shift(); 233 | delete workarray[elem.request]; 234 | 235 | if( elem.request ) 236 | { 237 | doSend( elem.request ); 238 | lastitem = elem; 239 | return; 240 | } 241 | } 242 | 243 | doSend('wx'); //Request RSSI. 244 | } 245 | 246 | function onError(evt) 247 | { 248 | $('#SystemStatusClicker').css("color", "red" ); 249 | commsup = 0; 250 | } 251 | 252 | function doSend(message) 253 | { 254 | websocket.send(message); 255 | } 256 | 257 | function IsTabOpen( objname ) 258 | { 259 | var obj = $( "#" + objname ); 260 | var opened = obj.is( '.opened' ); 261 | return opened != 0; 262 | } 263 | 264 | function ShowHideEvent( objname ) 265 | { 266 | var obj = $( "#" + objname ); 267 | obj.slideToggle( 'fast' ).toggleClass( 'opened' ); 268 | var opened = obj.is( '.opened' ); 269 | localStorage["sh" + objname] = opened?1:0; 270 | return opened!=0; 271 | } 272 | 273 | 274 | function IssueCustomCommand() 275 | { 276 | QueueOperation( $("#custom_command").val(), function( req,data) { $("#custom_command_response").val( data ); } ); 277 | } 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | function MakeDragDrop( divname, callback ) 289 | { 290 | var obj = $("#" + divname); 291 | obj.on('dragenter', function (e) 292 | { 293 | e.stopPropagation(); 294 | e.preventDefault(); 295 | $(this).css('border', '2px solid #0B85A1'); 296 | }); 297 | 298 | obj.on('dragover', function (e) 299 | { 300 | e.stopPropagation(); 301 | e.preventDefault(); 302 | }); 303 | 304 | obj.on('dragend', function (e) 305 | { 306 | e.stopPropagation(); 307 | e.preventDefault(); 308 | $(this).css('border', '2px dotted #0B85A1'); 309 | }); 310 | 311 | obj.on('drop', function (e) 312 | { 313 | $(this).css('border', '2px dotted #0B85A1'); 314 | e.preventDefault(); 315 | var files = e.originalEvent.dataTransfer.files; 316 | 317 | //We need to send dropped files to Server 318 | callback(files); 319 | }); 320 | } 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////// 329 | ///Below here are mostly just events... 330 | 331 | var sysset = null; 332 | var snchanged = false; 333 | var sdchanged = false; 334 | 335 | var lastpeerdata = ""; 336 | 337 | function CallbackForPeers(req,data) 338 | { 339 | if( data == lastpeerdata ) return; 340 | lastpeerdata = data; 341 | var lines = data.split( "\n" ); 342 | var searchcount = 0; 343 | if( lines.length > 0 ) 344 | { 345 | var line1 = lines[0].split( "\t" ); 346 | if( line1.length > 1 ) searchcount = Number( line1[1] ); 347 | } 348 | 349 | var htm = ""; 350 | for( var i = 1; i < lines.length; i++ ) 351 | { 352 | var elems = lines[i].split( "\t" ); 353 | if( elems.length < 4 ) continue; 354 | IP = HexToIP( elems[0] ); 355 | 356 | htm += ""; 357 | } 358 | htm += "
AddressServiceNameDescription
" + IP + "" + elems[1] + "" + elems[2] + "" + elems[3] + "
"; 359 | if( searchcount == 0 ) 360 | { 361 | htm += ""; 362 | } 363 | 364 | $("#peers").html( htm ); 365 | } 366 | 367 | function SysTickBack(req,data) 368 | { 369 | var params = data.split( "\t" ); 370 | if( !snchanged ) 371 | { 372 | $("#SystemName").prop( "value", params[3] ); 373 | $("#SystemName").removeClass( "unsaved-input"); 374 | } 375 | if( !sdchanged ) 376 | { 377 | $("#SystemDescription").prop( "value", params[4] ); 378 | $("#SystemDescription").removeClass( "unsaved-input"); 379 | } 380 | $("#ServiceName").html( params[5] ); 381 | $("#FreeHeap").html( params[6] ); 382 | 383 | QueueOperation( "BL", CallbackForPeers ); 384 | } 385 | 386 | function SystemInfoTick() 387 | { 388 | if( IsTabOpen('SystemStatus') ) 389 | { 390 | QueueOperation( "I", SysTickBack ); 391 | setTimeout( SystemInfoTick, 500 ); 392 | } 393 | else 394 | { 395 | //Stop. 396 | } 397 | } 398 | 399 | function SystemChangesReset() 400 | { 401 | snchanged = false; 402 | sdchanged = false; 403 | } 404 | 405 | function SystemUncommittedChanges() 406 | { 407 | if( sdchanged || snchanged ) return true; 408 | else return false; 409 | } 410 | 411 | function InitSystemTicker() 412 | { 413 | sysset = document.getElementById( "systemsettings" ); 414 | SystemInfoTick(); 415 | sysset.innerHTML = "\ 416 |
System Name:
System Description:
Service Name:
Free Heap:
\ 417 | \ 418 | \ 419 | \ 420 | \ 421 | \ 422 |

Search for others:

\ 423 |
"; 424 | $("#SystemName").on("input propertychange paste",function(){snchanged = true; $("#SystemName").addClass( "unsaved-input"); }); 425 | $("#SystemDescription").on("input propertychange paste",function(){sdchanged = true;$("#SystemDescription").addClass( "unsaved-input"); }); 426 | } 427 | 428 | 429 | 430 | did_wifi_get_config = false; 431 | is_data_ticker_running = false; 432 | is_waiting_on_stations = false; 433 | 434 | function ScanForWifi() 435 | { 436 | QueueOperation('WS', null); 437 | is_waiting_on_stations=true; 438 | IssueSystemMessage( "Scanning for Wifi..." ); 439 | } 440 | 441 | function KickWifiTicker() 442 | { 443 | if( !is_data_ticker_running ) 444 | WifiDataTicker(); 445 | } 446 | 447 | function BSSIDClick( i ) 448 | { 449 | var tlines = wifilines[i]; 450 | document.wifisection.wifitype.value = 1; 451 | document.wifisection.wificurname.value = tlines[0].substr(1); 452 | document.wifisection.wificurpassword.value = ""; 453 | document.wifisection.wifimac.value = tlines[1]; 454 | document.wifisection.wificurchannel.value = 0; 455 | 456 | ClickOpmode( 1 ); 457 | return false; 458 | } 459 | 460 | function ClickOpmode( i ) 461 | { 462 | if( i == 1 ) 463 | { 464 | document.wifisection.wificurname.disabled = false; 465 | document.wifisection.wificurpassword.disabled = false; 466 | document.wifisection.wifimac.disabled = false; 467 | document.wifisection.wificurchannel.disabled = true; 468 | } 469 | else 470 | { 471 | document.wifisection.wificurname.disabled = false; 472 | document.wifisection.wificurpassword.disabled = true; 473 | document.wifisection.wificurpassword.value = ""; 474 | document.wifisection.wifimac.disabled = true; 475 | document.wifisection.wificurchannel.disabled = false; 476 | } 477 | } 478 | 479 | function WifiDataTicker() 480 | { 481 | if( IsTabOpen('WifiSettings') ) 482 | { 483 | is_data_ticker_running = true; 484 | 485 | if( !did_wifi_get_config ) 486 | { 487 | QueueOperation( "WI", function(req,data) 488 | { 489 | var params = data.split( "\t" ); 490 | 491 | var opmode = Number( params[0].substr(2) ); 492 | document.wifisection.wifitype.value = opmode; 493 | document.wifisection.wificurname.value = params[1]; 494 | document.wifisection.wificurpassword.value = params[2]; 495 | document.wifisection.wifimac.value = params[3]; 496 | document.wifisection.wificurchannel.value = Number( params[4] ); 497 | 498 | ClickOpmode( opmode ); 499 | did_wifi_get_config = true; 500 | } ); 501 | } 502 | 503 | QueueOperation( "WR", function(req,data) { 504 | var lines = data.split( "\n" ); 505 | var innerhtml; 506 | if( data[0] == '!' ) return; //If no APs, don't deal with list. 507 | 508 | if( lines.length < 3 ) 509 | { 510 | innerhtml = "No APs found. Did you scan?"; 511 | if( is_waiting_on_stations ) 512 | { 513 | IssueSystemMessage( "No APs found." ); 514 | is_waiting_on_stations = false; 515 | } 516 | } 517 | else 518 | { 519 | if( is_waiting_on_stations ) 520 | { 521 | IssueSystemMessage( "Scan Complete." ); 522 | is_waiting_on_stations = false; 523 | } 524 | 525 | innerhtml = "" 526 | wifilines = []; 527 | for( i = 1; i < lines.length-1; i++ ) 528 | { 529 | tlines = lines[i].split( "\t" ); 530 | wifilines.push(tlines); 531 | var bssidval = "" + tlines[1]; 532 | innerhtml += ""; 533 | } 534 | } 535 | innerhtml += "
SSIDMACRSChEnc
" + tlines[0].substr(1) + "" + bssidval + "" + tlines[2] + "" + tlines[3] + "" + tlines[4] + "
"; 536 | document.getElementById("WifiStations").innerHTML = innerhtml; 537 | } ); 538 | setTimeout( WifiDataTicker, 500 ); 539 | } 540 | else 541 | { 542 | is_data_ticker_running = 0; 543 | } 544 | } 545 | 546 | function ChangeWifiConfig() 547 | { 548 | 549 | var st = "W"; 550 | st += document.wifisection.wifitype.value; 551 | st += "\t" + document.wifisection.wificurname.value; 552 | st += "\t" + document.wifisection.wificurpassword.value; 553 | st += "\t" + document.wifisection.wifimac.value; 554 | st += "\t" + document.wifisection.wificurchannel.value; 555 | QueueOperation( st ); 556 | did_wifi_get_config = false; 557 | } 558 | 559 | 560 | 561 | 562 | function TwiddleGPIO( gp ) 563 | { 564 | var st = "GF"; 565 | st += gp; 566 | QueueOperation( st ); 567 | } 568 | 569 | function GPIOInput( gp ) 570 | { 571 | var st = "GI"; 572 | st += gp; 573 | QueueOperation( st ); 574 | } 575 | 576 | function GPIOUpdate(req,data) { 577 | var secs = data.split( "\t" ); 578 | var op = 0; 579 | var n = Number(secs[2]); 580 | var m = Number(secs[1]); 581 | 582 | for( op = 0; op < 16; op++ ) 583 | { 584 | var b = $( "#ButtonGPIO" + op ); 585 | if( b ) 586 | { 587 | if( 1< 65536 ) 749 | { 750 | $("#innersystemflashtext").html( "0x00000 needs to fit in IRAM. Too big." ); return; 751 | } 752 | 753 | if( file2.size > 262144 ) 754 | { 755 | $("#innersystemflashtext").html( "0x40000 needs to fit in 256kB. Too big." ); return; 756 | } 757 | 758 | //Files check out. Start pushing. 759 | 760 | $("#innersystemflashtext").html( "Starting." ); 761 | 762 | var reader = new FileReader(); 763 | 764 | reader.onload = function(e) { 765 | var ctx = new Object(); 766 | ctx.file1 = file1; 767 | ctx.file2 = file2; 768 | ctx.current_state = 0; 769 | PushImageTo( e.target.result, flash_scratchpad_at, SystemPushImageProgress, ctx ); 770 | } 771 | 772 | reader.readAsArrayBuffer( file[0] ); 773 | return; 774 | } 775 | else 776 | { 777 | $("#innersystemflashtext").html( "Cannot accept anything other than 1 or 2 files." ); 778 | } 779 | } 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | function tohex8( c ) 790 | { 791 | var hex = c.toString(16); 792 | return hex.length == 1 ? "0" + hex : hex; 793 | } 794 | 795 | 796 | function HexToIP( hexstr ) 797 | { 798 | if( !hexstr ) return ""; 799 | return parseInt( hexstr.substr( 6, 2 ), 16 ) + "." + 800 | parseInt( hexstr.substr( 4, 2 ), 16 ) + "." + 801 | parseInt( hexstr.substr( 2, 2 ), 16 ) + "." + 802 | parseInt( hexstr.substr( 0, 2 ), 16 ); 803 | } 804 | 805 | function ContinueSystemFlash( fsrd, flashresponse, pushop ) 806 | { 807 | if( flashresponse[0] == '!' ) 808 | { 809 | pushop.status_callback( 0, flashresponse, pushop ); 810 | console.log( flashresponse ); 811 | return; 812 | } 813 | 814 | var cont = pushop.status_callback( 1, flashresponse, pushop ); 815 | 816 | if( !cont ) return; 817 | if( pushop.place >= pushop.padlen ) return; 818 | 819 | //If we are coming from a write, and now we need to erase the next block, do so. 820 | 821 | if( ( pushop.place % flash_blocksize ) == 0 && flashresponse[1] != 'B' ) 822 | { 823 | QueueOperation( "FB" + ((pushop.place+pushop.base_address)/flash_blocksize), function( x, y ) { ContinueSystemFlash( x, y, pushop ); } ); 824 | } 825 | else //Done erasing the next block, or coming off a write we don't need to erase? 826 | { 827 | var addy = pushop.place + pushop.base_address; 828 | var sendstr = "FX" + addy + "\t" + flash_sendsize + "\t"; 829 | for( var i = 0; i < flash_sendsize; i++ ) 830 | { 831 | sendstr += tohex8( pushop.paddata[pushop.place++] ); 832 | } 833 | QueueOperation( sendstr, function( x, y ) { ContinueSystemFlash( x, y, pushop ); } ); 834 | } 835 | } 836 | 837 | //The signature for status callback is: function AVRStatusCallback( is_ok, comment, pushop ) 838 | //If pushop.place == pushop.padlen, no further callbacks will continue, even if true is returned. 839 | //you must return "true." Returning false will cease further pushing. 840 | //This function returns an object with all properties about the transfer. 841 | //WARNING: "location" must be block (65536) aligned. 842 | function PushImageTo( arraydata, location, status_callback, ctx ) 843 | { 844 | if( location & 0xffff != 0 ) 845 | { 846 | console.log( "Error: to address not 65,536 aligned." ); 847 | return null; 848 | } 849 | 850 | var pushop = Object(); 851 | pushop.padlen = Math.floor(((arraydata.byteLength-1)/flash_sendsize)+1)*flash_sendsize; 852 | pushop.paddata = new Uint8Array( pushop.padlen, 0 ); 853 | pushop.paddata.set( new Uint8Array( arraydata ), 0 ); 854 | pushop.status_callback = status_callback; 855 | pushop.place = 0; 856 | pushop.base_address = location; 857 | pushop.ctx = ctx; 858 | 859 | ContinueSystemFlash( null, "Starting", pushop ); 860 | 861 | return pushop; 862 | } 863 | 864 | 865 | 866 | 867 | 868 | /* MD5 implementation minified from: http://blog.faultylabs.com/files/md5.js 869 | Javascript MD5 library - version 0.4 Coded (2011) by Luigi Galli - LG@4e71.org - http://faultylabs.com 870 | Thanks to: Roberto Viola The below code is PUBLIC DOMAIN - NO WARRANTY! 871 | */ 872 | "undefined"==typeof faultylabs&&(faultylabs={}),faultylabs.MD5=function(n){function r(n){var r=(n>>>0).toString(16);return"00000000".substr(0,8-r.length)+r}function t(n){for(var r=[],t=0;tt;t++)r.push(255&n),n>>>=8;return r}function o(n,r){return n<>>32-r}function a(n,r,t){return n&r|~n&t}function f(n,r,t){return t&n|~t&r}function u(n,r,t){return n^r^t}function i(n,r,t){return r^(n|~t)}function c(n,r){return n[r+3]<<24|n[r+2]<<16|n[r+1]<<8|n[r]}function s(n){for(var r=[],t=0;t=0;o--)e=arguments[o],t=255&e,e>>>=8,t<<=8,t|=255&e,e>>>=8,t<<=8,t|=255&e,e>>>=8,t<<=8,t|=e,n+=r(t);return n}function y(n){for(var r=new Array(n.length),t=0;t56){for(var s=0;64-t>s;s++)A.push(0);t=A.length%64}for(s=0;56-t>s;s++)A.push(0);A=A.concat(e(8*r));var y=1732584193,p=4023233417,g=2562383102,v=271733878,b=0,d=0,U=0,m=0;for(s=0;s< Charles Lohr, see LICENSE file for more info. 2 | // 3 | //This particular file may be licensed under the MIT/x11, New BSD or ColorChord Licenses. 4 | var wsUri = "ws://" + location.host + "/d/ws/issue"; 5 | var output; 6 | var websocket; 7 | var commsup = 0; 8 | 9 | var mpfs_start_at = 65536; //1048576; NOTE: If you select 1048576, it will override the 65536 sector, but has much more room. 10 | var flash_scratchpad_at = 524288; 11 | var flash_blocksize = 65536; 12 | var flash_sendsize = 256; 13 | //Push objects that have: 14 | // .request 15 | // .callback = function( ref (this object), data ); 16 | 17 | var workqueue = []; 18 | var wifilines = []; 19 | var workarray = {}; 20 | var lastitem; 21 | 22 | var SystemMessageTimeout = null; 23 | function IssueSystemMessage( msg ) 24 | { 25 | var elem = $( "#SystemMessage" ); 26 | elem.hide(); 27 | elem.html( "" + msg + "" ); 28 | elem.slideToggle( 'fast' ); 29 | if( SystemMessageTimeout != null ) clearTimeout(SystemMessageTimeout); 30 | SystemMessageTimeout = setTimeout( function() { SystemMessageTimeout = null; $( "#SystemMessage" ).fadeOut( 'slow' ) }, 3000 ); 31 | } 32 | 33 | function QueueOperation( command, callback, extra ) 34 | { 35 | if( workarray[command] == 1 ) 36 | { 37 | return; 38 | } 39 | 40 | workarray[command] = 1; 41 | var vp = new Object(); 42 | vp.callback = callback; 43 | vp.extra = extra; 44 | vp.request = command; 45 | workqueue.push( vp ); 46 | } 47 | 48 | 49 | function init() 50 | { 51 | GPIOlines = ''; 52 | for(var i=0; i<16; ++i) 53 | GPIOlines += ""+ i 54 | + "" 55 | + "" 56 | + ""; 57 | 58 | $('#MainMenu > tbody:first-child').before( "\ 59 | \ 60 | \ 61 |
\ 62 |
\ 63 |
\n
" 64 | ); 65 | 66 | $('#MainMenu > tbody:last-child').after( "\ 67 | \ 68 | \ 69 |
\ 70 |
\ 71 | Current Configuration: (May deviate from default configuration, reset here if in doubt)
\ 72 | \ 73 | \ 74 | \ 75 | \ 76 | \ 77 | \ 78 | \ 79 |
Type:Station (Connect to infrastructure)
AP (Broadcast a new AP)
SSID:
PASS:
MAC: (Ignored in softAP mode)
Chan: (Ignored in Station mode)
(Automatically saves to flash)
\ 80 | Scanned Stations: \ 81 |
\ 82 | \ 83 |
\ 84 | \ 85 | \ 86 | \ 87 |
\ 88 |
\ 89 | Command: \ 90 |
\ 91 | \ 92 |
\ 93 | \ 94 | \ 95 | \ 96 |
\ 97 | " + 98 | GPIOlines 99 | + "
\ 100 | \ 101 | \ 102 | \ 103 |
\ 104 |
\ 105 |
Drop or browse for system (0x000.. 0x400...) or web (.mpfs) reflash files.
\ 106 |
" 107 | ); 108 | 109 | MakeDragDrop( "InnerSystemReflash", DragDropSystemFiles ); 110 | $("#dragndropersystem").change(function() { DragDropSystemFiles(this.files ); }); 111 | 112 | $( ".collapsible" ).each(function( index ) { 113 | if( localStorage["sh" + this.id] > 0.5 ) 114 | { 115 | $( this ).show().toggleClass( 'opened' ); 116 | // console.log( "OPEN: " + this.id ); 117 | } 118 | }); 119 | 120 | $("#custom_command_response").val( "" ); 121 | 122 | //Preclude drag and drop on rest of document in event user misses firmware boxes. 123 | donothing = function(e) {e.stopPropagation();e.preventDefault();}; 124 | $(document).on('drop', donothing ); 125 | $(document).on('dragover', donothing ); 126 | $(document).on('dragenter', donothing ); 127 | 128 | output = document.getElementById("output"); 129 | 130 | KickWifiTicker(); 131 | GPIODataTickerStart(); 132 | InitSystemTicker(); 133 | 134 | console.log( "Load complete.\n" ); 135 | Ticker(); 136 | } 137 | 138 | window.addEventListener("load", init, false); 139 | 140 | 141 | function StartWebSocket() 142 | { 143 | output.innerHTML = "Connecting..."; 144 | if( websocket ) websocket.close(); 145 | workarray = {}; 146 | workqueue = []; 147 | lastitem = null; 148 | websocket = new WebSocket(wsUri); 149 | websocket.onopen = function(evt) { onOpen(evt) }; 150 | websocket.onclose = function(evt) { onClose(evt) }; 151 | websocket.onmessage = function(evt) { onMessage(evt) }; 152 | websocket.onerror = function(evt) { onError(evt) }; 153 | } 154 | 155 | function onOpen(evt) 156 | { 157 | doSend('e' ); 158 | } 159 | 160 | function onClose(evt) 161 | { 162 | $('#SystemStatusClicker').css("color", "red" ); 163 | commsup = 0; 164 | } 165 | 166 | var msg = 0; 167 | var tickmessage = 0; 168 | var lasthz = 0; 169 | var time_since_hz = 10; //Make it realize it was disconnected to begin with. 170 | 171 | function Ticker() 172 | { 173 | setTimeout( Ticker, 1000 ); 174 | 175 | lasthz = (msg - tickmessage); 176 | tickmessage = msg; 177 | if( lasthz == 0 ) 178 | { 179 | time_since_hz++; 180 | if( time_since_hz > 3 ) 181 | { 182 | $('#SystemStatusClicker').css("color", "red" ); 183 | $('#SystemStatusClicker').prop( "value", "System Offline" ); 184 | if( commsup != 0 && !is_waiting_on_stations ) IssueSystemMessage( "Comms Lost." ); 185 | commsup = 0; 186 | StartWebSocket(); 187 | } 188 | else 189 | $('#SystemStatusClicker').prop( "value", "System " + 0 + "Hz" ); 190 | } 191 | else 192 | { 193 | time_since_hz = 0; 194 | $('#SystemStatusClicker').prop( "value", "System " + lasthz + "Hz" ); 195 | } 196 | } 197 | 198 | 199 | function onMessage(evt) 200 | { 201 | msg++; 202 | 203 | 204 | if( commsup != 1 ) 205 | { 206 | commsup = 1; 207 | $('#SystemStatusClicker').css("color", "green" ); 208 | IssueSystemMessage( "Comms Established." ); 209 | } 210 | 211 | 212 | if( lastitem ) 213 | { 214 | if( lastitem.callback ) 215 | { 216 | lastitem.callback( lastitem, evt.data ); 217 | lastitem = null; 218 | } 219 | } 220 | else 221 | { 222 | if( evt.data.length > 2 ) 223 | { 224 | var wxresp = evt.data.substr(2).split("\t"); 225 | output.innerHTML = "

Messages: " + msg + "

RSSI: " + wxresp[0] + " / IP: " + ((wxresp.length>1)?HexToIP( wxresp[1] ):"") + "

"; 226 | } 227 | } 228 | 229 | 230 | if( workqueue.length ) 231 | { 232 | var elem = workqueue.shift(); 233 | delete workarray[elem.request]; 234 | 235 | if( elem.request ) 236 | { 237 | doSend( elem.request ); 238 | lastitem = elem; 239 | return; 240 | } 241 | } 242 | 243 | doSend('wx'); //Request RSSI. 244 | } 245 | 246 | function onError(evt) 247 | { 248 | $('#SystemStatusClicker').css("color", "red" ); 249 | commsup = 0; 250 | } 251 | 252 | function doSend(message) 253 | { 254 | websocket.send(message); 255 | } 256 | 257 | function IsTabOpen( objname ) 258 | { 259 | var obj = $( "#" + objname ); 260 | var opened = obj.is( '.opened' ); 261 | return opened != 0; 262 | } 263 | 264 | function ShowHideEvent( objname ) 265 | { 266 | var obj = $( "#" + objname ); 267 | obj.slideToggle( 'fast' ).toggleClass( 'opened' ); 268 | var opened = obj.is( '.opened' ); 269 | localStorage["sh" + objname] = opened?1:0; 270 | return opened!=0; 271 | } 272 | 273 | 274 | function IssueCustomCommand() 275 | { 276 | QueueOperation( $("#custom_command").val(), function( req,data) { $("#custom_command_response").val( data ); } ); 277 | } 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | function MakeDragDrop( divname, callback ) 289 | { 290 | var obj = $("#" + divname); 291 | obj.on('dragenter', function (e) 292 | { 293 | e.stopPropagation(); 294 | e.preventDefault(); 295 | $(this).css('border', '2px solid #0B85A1'); 296 | }); 297 | 298 | obj.on('dragover', function (e) 299 | { 300 | e.stopPropagation(); 301 | e.preventDefault(); 302 | }); 303 | 304 | obj.on('dragend', function (e) 305 | { 306 | e.stopPropagation(); 307 | e.preventDefault(); 308 | $(this).css('border', '2px dotted #0B85A1'); 309 | }); 310 | 311 | obj.on('drop', function (e) 312 | { 313 | $(this).css('border', '2px dotted #0B85A1'); 314 | e.preventDefault(); 315 | var files = e.originalEvent.dataTransfer.files; 316 | 317 | //We need to send dropped files to Server 318 | callback(files); 319 | }); 320 | } 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////// 329 | ///Below here are mostly just events... 330 | 331 | var sysset = null; 332 | var snchanged = false; 333 | var sdchanged = false; 334 | 335 | var lastpeerdata = ""; 336 | 337 | function CallbackForPeers(req,data) 338 | { 339 | if( data == lastpeerdata ) return; 340 | lastpeerdata = data; 341 | var lines = data.split( "\n" ); 342 | var searchcount = 0; 343 | if( lines.length > 0 ) 344 | { 345 | var line1 = lines[0].split( "\t" ); 346 | if( line1.length > 1 ) searchcount = Number( line1[1] ); 347 | } 348 | 349 | var htm = ""; 350 | for( var i = 1; i < lines.length; i++ ) 351 | { 352 | var elems = lines[i].split( "\t" ); 353 | if( elems.length < 4 ) continue; 354 | IP = HexToIP( elems[0] ); 355 | 356 | htm += ""; 357 | } 358 | htm += "
AddressServiceNameDescription
" + IP + "" + elems[1] + "" + elems[2] + "" + elems[3] + "
"; 359 | if( searchcount == 0 ) 360 | { 361 | htm += ""; 362 | } 363 | 364 | $("#peers").html( htm ); 365 | } 366 | 367 | function SysTickBack(req,data) 368 | { 369 | var params = data.split( "\t" ); 370 | if( !snchanged ) 371 | { 372 | $("#SystemName").prop( "value", params[3] ); 373 | $("#SystemName").removeClass( "unsaved-input"); 374 | } 375 | if( !sdchanged ) 376 | { 377 | $("#SystemDescription").prop( "value", params[4] ); 378 | $("#SystemDescription").removeClass( "unsaved-input"); 379 | } 380 | $("#ServiceName").html( params[5] ); 381 | $("#FreeHeap").html( params[6] ); 382 | 383 | QueueOperation( "BL", CallbackForPeers ); 384 | } 385 | 386 | function SystemInfoTick() 387 | { 388 | if( IsTabOpen('SystemStatus') ) 389 | { 390 | QueueOperation( "I", SysTickBack ); 391 | setTimeout( SystemInfoTick, 500 ); 392 | } 393 | else 394 | { 395 | //Stop. 396 | } 397 | } 398 | 399 | function SystemChangesReset() 400 | { 401 | snchanged = false; 402 | sdchanged = false; 403 | } 404 | 405 | function SystemUncommittedChanges() 406 | { 407 | if( sdchanged || snchanged ) return true; 408 | else return false; 409 | } 410 | 411 | function InitSystemTicker() 412 | { 413 | sysset = document.getElementById( "systemsettings" ); 414 | SystemInfoTick(); 415 | sysset.innerHTML = "\ 416 |
System Name:
System Description:
Service Name:
Free Heap:
\ 417 | \ 418 | \ 419 | \ 420 | \ 421 | \ 422 |

Search for others:

\ 423 |
"; 424 | $("#SystemName").on("input propertychange paste",function(){snchanged = true; $("#SystemName").addClass( "unsaved-input"); }); 425 | $("#SystemDescription").on("input propertychange paste",function(){sdchanged = true;$("#SystemDescription").addClass( "unsaved-input"); }); 426 | } 427 | 428 | 429 | 430 | did_wifi_get_config = false; 431 | is_data_ticker_running = false; 432 | is_waiting_on_stations = false; 433 | 434 | function ScanForWifi() 435 | { 436 | QueueOperation('WS', null); 437 | is_waiting_on_stations=true; 438 | IssueSystemMessage( "Scanning for Wifi..." ); 439 | } 440 | 441 | function KickWifiTicker() 442 | { 443 | if( !is_data_ticker_running ) 444 | WifiDataTicker(); 445 | } 446 | 447 | function BSSIDClick( i ) 448 | { 449 | var tlines = wifilines[i]; 450 | document.wifisection.wifitype.value = 1; 451 | document.wifisection.wificurname.value = tlines[0].substr(1); 452 | document.wifisection.wificurpassword.value = ""; 453 | document.wifisection.wifimac.value = tlines[1]; 454 | document.wifisection.wificurchannel.value = 0; 455 | 456 | ClickOpmode( 1 ); 457 | return false; 458 | } 459 | 460 | function ClickOpmode( i ) 461 | { 462 | if( i == 1 ) 463 | { 464 | document.wifisection.wificurname.disabled = false; 465 | document.wifisection.wificurpassword.disabled = false; 466 | document.wifisection.wifimac.disabled = false; 467 | document.wifisection.wificurchannel.disabled = true; 468 | } 469 | else 470 | { 471 | document.wifisection.wificurname.disabled = false; 472 | document.wifisection.wificurpassword.disabled = true; 473 | document.wifisection.wificurpassword.value = ""; 474 | document.wifisection.wifimac.disabled = true; 475 | document.wifisection.wificurchannel.disabled = false; 476 | } 477 | } 478 | 479 | function WifiDataTicker() 480 | { 481 | if( IsTabOpen('WifiSettings') ) 482 | { 483 | is_data_ticker_running = true; 484 | 485 | if( !did_wifi_get_config ) 486 | { 487 | QueueOperation( "WI", function(req,data) 488 | { 489 | var params = data.split( "\t" ); 490 | 491 | var opmode = Number( params[0].substr(2) ); 492 | document.wifisection.wifitype.value = opmode; 493 | document.wifisection.wificurname.value = params[1]; 494 | document.wifisection.wificurpassword.value = params[2]; 495 | document.wifisection.wifimac.value = params[3]; 496 | document.wifisection.wificurchannel.value = Number( params[4] ); 497 | 498 | ClickOpmode( opmode ); 499 | did_wifi_get_config = true; 500 | } ); 501 | } 502 | 503 | QueueOperation( "WR", function(req,data) { 504 | var lines = data.split( "\n" ); 505 | var innerhtml; 506 | if( data[0] == '!' ) return; //If no APs, don't deal with list. 507 | 508 | if( lines.length < 3 ) 509 | { 510 | innerhtml = "No APs found. Did you scan?"; 511 | if( is_waiting_on_stations ) 512 | { 513 | IssueSystemMessage( "No APs found." ); 514 | is_waiting_on_stations = false; 515 | } 516 | } 517 | else 518 | { 519 | if( is_waiting_on_stations ) 520 | { 521 | IssueSystemMessage( "Scan Complete." ); 522 | is_waiting_on_stations = false; 523 | } 524 | 525 | innerhtml = "" 526 | wifilines = []; 527 | for( i = 1; i < lines.length-1; i++ ) 528 | { 529 | tlines = lines[i].split( "\t" ); 530 | wifilines.push(tlines); 531 | var bssidval = "" + tlines[1]; 532 | innerhtml += ""; 533 | } 534 | } 535 | innerhtml += "
SSIDMACRSChEnc
" + tlines[0].substr(1) + "" + bssidval + "" + tlines[2] + "" + tlines[3] + "" + tlines[4] + "
"; 536 | document.getElementById("WifiStations").innerHTML = innerhtml; 537 | } ); 538 | setTimeout( WifiDataTicker, 500 ); 539 | } 540 | else 541 | { 542 | is_data_ticker_running = 0; 543 | } 544 | } 545 | 546 | function ChangeWifiConfig() 547 | { 548 | 549 | var st = "W"; 550 | st += document.wifisection.wifitype.value; 551 | st += "\t" + document.wifisection.wificurname.value; 552 | st += "\t" + document.wifisection.wificurpassword.value; 553 | st += "\t" + document.wifisection.wifimac.value; 554 | st += "\t" + document.wifisection.wificurchannel.value; 555 | QueueOperation( st ); 556 | did_wifi_get_config = false; 557 | } 558 | 559 | 560 | 561 | 562 | function TwiddleGPIO( gp ) 563 | { 564 | var st = "GF"; 565 | st += gp; 566 | QueueOperation( st ); 567 | } 568 | 569 | function GPIOInput( gp ) 570 | { 571 | var st = "GI"; 572 | st += gp; 573 | QueueOperation( st ); 574 | } 575 | 576 | function GPIOUpdate(req,data) { 577 | var secs = data.split( "\t" ); 578 | var op = 0; 579 | var n = Number(secs[2]); 580 | var m = Number(secs[1]); 581 | 582 | for( op = 0; op < 16; op++ ) 583 | { 584 | var b = $( "#ButtonGPIO" + op ); 585 | if( b ) 586 | { 587 | if( 1< 65536 ) 749 | { 750 | $("#innersystemflashtext").html( "0x00000 needs to fit in IRAM. Too big." ); return; 751 | } 752 | 753 | if( file2.size > 262144 ) 754 | { 755 | $("#innersystemflashtext").html( "0x40000 needs to fit in 256kB. Too big." ); return; 756 | } 757 | 758 | //Files check out. Start pushing. 759 | 760 | $("#innersystemflashtext").html( "Starting." ); 761 | 762 | var reader = new FileReader(); 763 | 764 | reader.onload = function(e) { 765 | var ctx = new Object(); 766 | ctx.file1 = file1; 767 | ctx.file2 = file2; 768 | ctx.current_state = 0; 769 | PushImageTo( e.target.result, flash_scratchpad_at, SystemPushImageProgress, ctx ); 770 | } 771 | 772 | reader.readAsArrayBuffer( file[0] ); 773 | return; 774 | } 775 | else 776 | { 777 | $("#innersystemflashtext").html( "Cannot accept anything other than 1 or 2 files." ); 778 | } 779 | } 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | function tohex8( c ) 790 | { 791 | var hex = c.toString(16); 792 | return hex.length == 1 ? "0" + hex : hex; 793 | } 794 | 795 | 796 | function HexToIP( hexstr ) 797 | { 798 | if( !hexstr ) return ""; 799 | return parseInt( hexstr.substr( 6, 2 ), 16 ) + "." + 800 | parseInt( hexstr.substr( 4, 2 ), 16 ) + "." + 801 | parseInt( hexstr.substr( 2, 2 ), 16 ) + "." + 802 | parseInt( hexstr.substr( 0, 2 ), 16 ); 803 | } 804 | 805 | function ContinueSystemFlash( fsrd, flashresponse, pushop ) 806 | { 807 | if( flashresponse[0] == '!' ) 808 | { 809 | pushop.status_callback( 0, flashresponse, pushop ); 810 | console.log( flashresponse ); 811 | return; 812 | } 813 | 814 | var cont = pushop.status_callback( 1, flashresponse, pushop ); 815 | 816 | if( !cont ) return; 817 | if( pushop.place >= pushop.padlen ) return; 818 | 819 | //If we are coming from a write, and now we need to erase the next block, do so. 820 | 821 | if( ( pushop.place % flash_blocksize ) == 0 && flashresponse[1] != 'B' ) 822 | { 823 | QueueOperation( "FB" + ((pushop.place+pushop.base_address)/flash_blocksize), function( x, y ) { ContinueSystemFlash( x, y, pushop ); } ); 824 | } 825 | else //Done erasing the next block, or coming off a write we don't need to erase? 826 | { 827 | var addy = pushop.place + pushop.base_address; 828 | var sendstr = "FX" + addy + "\t" + flash_sendsize + "\t"; 829 | for( var i = 0; i < flash_sendsize; i++ ) 830 | { 831 | sendstr += tohex8( pushop.paddata[pushop.place++] ); 832 | } 833 | QueueOperation( sendstr, function( x, y ) { ContinueSystemFlash( x, y, pushop ); } ); 834 | } 835 | } 836 | 837 | //The signature for status callback is: function AVRStatusCallback( is_ok, comment, pushop ) 838 | //If pushop.place == pushop.padlen, no further callbacks will continue, even if true is returned. 839 | //you must return "true." Returning false will cease further pushing. 840 | //This function returns an object with all properties about the transfer. 841 | //WARNING: "location" must be block (65536) aligned. 842 | function PushImageTo( arraydata, location, status_callback, ctx ) 843 | { 844 | if( location & 0xffff != 0 ) 845 | { 846 | console.log( "Error: to address not 65,536 aligned." ); 847 | return null; 848 | } 849 | 850 | var pushop = Object(); 851 | pushop.padlen = Math.floor(((arraydata.byteLength-1)/flash_sendsize)+1)*flash_sendsize; 852 | pushop.paddata = new Uint8Array( pushop.padlen, 0 ); 853 | pushop.paddata.set( new Uint8Array( arraydata ), 0 ); 854 | pushop.status_callback = status_callback; 855 | pushop.place = 0; 856 | pushop.base_address = location; 857 | pushop.ctx = ctx; 858 | 859 | ContinueSystemFlash( null, "Starting", pushop ); 860 | 861 | return pushop; 862 | } 863 | 864 | 865 | 866 | 867 | 868 | /* MD5 implementation minified from: http://blog.faultylabs.com/files/md5.js 869 | Javascript MD5 library - version 0.4 Coded (2011) by Luigi Galli - LG@4e71.org - http://faultylabs.com 870 | Thanks to: Roberto Viola The below code is PUBLIC DOMAIN - NO WARRANTY! 871 | */ 872 | "undefined"==typeof faultylabs&&(faultylabs={}),faultylabs.MD5=function(n){function r(n){var r=(n>>>0).toString(16);return"00000000".substr(0,8-r.length)+r}function t(n){for(var r=[],t=0;tt;t++)r.push(255&n),n>>>=8;return r}function o(n,r){return n<>>32-r}function a(n,r,t){return n&r|~n&t}function f(n,r,t){return t&n|~t&r}function u(n,r,t){return n^r^t}function i(n,r,t){return r^(n|~t)}function c(n,r){return n[r+3]<<24|n[r+2]<<16|n[r+1]<<8|n[r]}function s(n){for(var r=[],t=0;t=0;o--)e=arguments[o],t=255&e,e>>>=8,t<<=8,t|=255&e,e>>>=8,t<<=8,t|=255&e,e>>>=8,t<<=8,t|=e,n+=r(t);return n}function y(n){for(var r=new Array(n.length),t=0;t56){for(var s=0;64-t>s;s++)A.push(0);t=A.length%64}for(s=0;56-t>s;s++)A.push(0);A=A.concat(e(8*r));var y=1732584193,p=4023233417,g=2562383102,v=271733878,b=0,d=0,U=0,m=0;for(s=0;s