├── README.md ├── docs └── WM_WiFi_自由通信接口使用指导_V0.2.pdf ├── hopping-led-demo.md ├── rf-center-frequency.md ├── rf-channel-bandwidth.md ├── screenshots ├── 20201101140901.jpg ├── 20201101141230.jpg ├── 20201101141251.jpg ├── 20201101141313.jpg ├── 20201101144440.jpg ├── 20201101145004.jpg └── 20201103143319.png ├── w60x-rf-hack └── w60x-rf-hack.ino ├── w60x-rf-rx └── w60x-rf-rx.ino └── w60x-rf-tx └── w60x-rf-tx.ino /README.md: -------------------------------------------------------------------------------- 1 | # w60x-rf-hacking 2 | Winnermicro W60x Wi-Fi library reverse engineering notes & hackings 3 | 4 | [zh-cn: 关于扩展中心频率的一点探索](https://github.com/libc0607/w60x-rf-hacking/blob/main/rf-center-frequency.md) 5 | [zh-cn: 关于 5MHz/10MHz 频宽模式](https://github.com/libc0607/w60x-rf-hacking/blob/main/rf-channel-bandwidth.md) 6 | [zh-cn: 一个简单的跳频通信点灯 Demo](https://github.com/libc0607/w60x-rf-hacking/blob/main/hopping-led-demo.md) 7 | 8 | -------------------------------------------------------------------------------- /docs/WM_WiFi_自由通信接口使用指导_V0.2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libc0607/w60x-rf-hacking/f2efe9ce291aa4ed37e69c99e9e939c995b5b66f/docs/WM_WiFi_自由通信接口使用指导_V0.2.pdf -------------------------------------------------------------------------------- /hopping-led-demo.md: -------------------------------------------------------------------------------- 1 | ### 一个简单的跳频点灯 Demo 2 | 3 | 代码在 [w60x-rf-rx/ (接收端)](https://github.com/libc0607/w60x-rf-hacking/tree/main/w60x-rf-rx) 和 [w60x-rf-tx/ (发射端)](https://github.com/libc0607/w60x-rf-hacking/tree/main/w60x-rf-tx) 4 | 5 | 这些代码需要运行在两块 W60x 开发板上,我这里使用了两块 TB-01 6 | 7 | 这个 Demo 的功能描述如下: 8 | 9 | 发射端会循环在 2.17GHz ~ 2.87GHz 之间,以 100MHz 步进跳频,发送一个包含自定义信息的 RTS 包; 10 | 每发送一个包改变一次 PB_14 上连接的 LED 的状态 11 | 12 | 接收端上电后会在其中一个频点监听,当收到包后便跟随跳到下一个频点; 13 | 每收到一个包改变一次 PB_14 上连接的 LED 的状态 14 | 15 | 所以如果它们可以正常通信,两边的 LED 会一起闪 16 | 17 | 18 | -------------------------------------------------------------------------------- /rf-center-frequency.md: -------------------------------------------------------------------------------- 1 | # 关于扩展中心频率的一点探索 2 | 3 | W600仅有libwlan没有开源,但是保留了符号。 4 | 首先用7z解压,其中的1.txt记录了每个.o文件中对外提供的函数接口 5 | 6 | ![7z](https://github.com/libc0607/w60x-rf-hacking/blob/main/screenshots/20201101141251.jpg) 7 | 8 | ![1txt](https://github.com/libc0607/w60x-rf-hacking/blob/main/screenshots/20201101141230.jpg) 9 | 10 | 11 | 通过搜索channel等关键词,觉得tls_wl_rf.o中应该有比较有趣的东西 12 | 载入IDA Pro,看到函数列表 13 | 14 | ![func-list](https://github.com/libc0607/w60x-rf-hacking/blob/main/screenshots/20201101140901.jpg) 15 | 16 | wm_rf_set_channel很是显眼,反编译出如下 17 | 18 | ``` 19 | int *__fastcall wm_rf_set_channel(int a1, unsigned int a2) 20 | { 21 | unsigned int v2; // r4 22 | int v3; // r5 23 | int v4; // r0 24 | int v5; // r1 25 | unsigned int v6; // r0 26 | int v7; // r6 27 | int v8; // r0 28 | int *result; // r0 29 | 30 | v2 = a2; 31 | v3 = a1; 32 | if ( a2 <= 1 ) 33 | { 34 | rf_spi_write(rf_chan24g_20m[2 * a1]); 35 | rf_spi_write(rf_chan24g_20m[2 * v3 + 1]); 36 | v4 = wm_rf_band_switch(0); 37 | v5 = tls_os_set_critical(v4); 38 | v6 = MEMORY[0x40001400] & 0xFFFFFFDF; 39 | LABEL_8: 40 | MEMORY[0x40001400] = v6; 41 | tls_os_release_critical(v5); 42 | goto LABEL_9; 43 | } 44 | if ( a2 <= 3 ) 45 | { 46 | if ( a2 == 2 ) 47 | v7 = central_freq[2 * a1]; 48 | else 49 | v7 = central_freq[2 * a1 + 1]; 50 | rf_spi_write(rf_chan24g_20m[2 * v7]); 51 | rf_spi_write(rf_chan24g_20m[2 * v7 + 1]); 52 | v8 = wm_rf_band_switch(1); 53 | v5 = tls_os_set_critical(v8); 54 | if ( v2 == 2 ) 55 | v6 = MEMORY[0x40001400] & 0xFFFEFF3F | 0xA0; 56 | else 57 | v6 = MEMORY[0x40001400] & 0xFFFFFF3F | 0x100E0; 58 | goto LABEL_8; 59 | } 60 | LABEL_9: 61 | result = &hed_rf_current_channel; 62 | hed_rf_current_channel = v3; 63 | *(_DWORD *)&hed_rf_chan_type = v2; 64 | return result; 65 | } 66 | ``` 67 | 68 | 69 | 70 | 这里明显调用了一个 rf_spi_write() 71 | ``` 72 | int __fastcall rf_spi_write(int a1) 73 | { 74 | MEMORY[0x40011408] = a1 << 10; 75 | tls_wl_delay(1); 76 | MEMORY[0x40011400] = 1; 77 | while ( MEMORY[0x40011404] & 0x40000 ) 78 | ; 79 | return tls_wl_delay(1); 80 | } 81 | int __fastcall rf_spi_read(int a1) 82 | { 83 | MEMORY[0x40011408] = (a1 << 27) | 0x4000000; 84 | tls_wl_delay(10); 85 | MEMORY[0x40011400] = 1; 86 | while ( MEMORY[0x40011404] & 0x40000 ) 87 | ; 88 | tls_wl_delay(200); 89 | return MEMORY[0x4001140C] >> 16; 90 | } 91 | ``` 92 | 93 | 看到这里直接操作了寄存器,查找手册中的寄存器分布 94 | 95 | ![reg1](https://github.com/libc0607/w60x-rf-hacking/blob/main/screenshots/20201101144440.jpg) 96 | 97 | ![reg2](https://github.com/libc0607/w60x-rf-hacking/blob/main/screenshots/20201101145004.jpg) 98 | 99 | 100 | 可以猜测,他们在Wi-Fi部分使用的频率合成器是通过SPI接口控制的,他们在APB上挂了一个简易的SPI控制器用来控制频率合成器 101 | 根据读写函数,容易猜测该简易SPI控制器的寄存器 MEMORY[0x40011408] 的结构为 102 | ``` 103 | 5'b + 1'b + 16'b + 10'b 104 | ``` 105 | 106 | 那接下来的方向就是找出他们往频率合成器中写了什么数据 107 | 108 | wm_rf_set_channel 这个函数中涉及了两个表:rf_chan24g_20m[] 与 central_freq[] 109 | ``` 110 | .data:000009B4 EXPORT rf_chan24g_20m 111 | .data:000009B4 ; _DWORD rf_chan24g_20m[30] 112 | .data:000009B4 rf_chan24g_20m DCD 0, 0, 0x2A203, 0x43333, 0x2A204, 0x48888, 0x2A205 113 | .data:000009B4 ; DATA XREF: wm_rf_set_channel+4↑o 114 | .data:000009B4 ; wm_rf_set_channel:loc_1BA↑o ... 115 | .data:000009B4 DCD 0x4DDDD, 0x2A207, 0x43333, 0x2A208, 0x48888, 0x2A209 116 | .data:000009B4 DCD 0x4DDDD, 0x2A20B, 0x43333, 0x2A20C, 0x48888, 0x2A20D 117 | .data:000009B4 DCD 0x4DDDD, 0x2A20F, 0x43333, 0x2A600, 0x48888, 0x2A601 118 | .data:000009B4 DCD 0x4DDDD, 0x2A603, 0x43333, 0x2A606, 0x46666 119 | ``` 120 | ``` 121 | .constdata:000008BC EXPORT central_freq 122 | .constdata:000008BC ; _DWORD central_freq[30] 123 | .constdata:000008BC central_freq DCD 0, 0, 3, 3, 4, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6 124 | .constdata:000008BC ; DATA XREF: wm_rf_set_channel+3C↑o 125 | .constdata:000008BC ; wm_rf_init:off_438↑o ... 126 | .constdata:000008BC DCD 0xA, 7, 0xB, 8, 0xC, 9, 0xD, 0xA, 0xA, 0xB, 0xB, 0 ; Alternative name is 'BuildAttributes$$THM_ISAv4$P$D$K$B$S$PE$A:L22UL41UL21$X:L11$S22US41US21$IEEE1$IW$USESV6$~STKCKD$USESV7$~SHL$OSPACE$EBA8$REQ8$PRES8$EABIv2' 127 | .constdata:000008BC DCD 0 128 | .constdata:000008BC ; .constdata ends 129 | .constdata:000008BC 130 | ``` 131 | 132 | 这种 0x3333, 0x8888, 0xDDDD 的感觉很像是频率合成器的小数部分,而central_freq这个一看就明白了是给ht40-和ht40+用的。。 133 | 这样 wm_rf_set_channel 的两个参数就容易明白了,分别为频道与带宽模式 134 | 结合前面猜出的结构,整理往 rf synth 中某个寄存器可能写入的数据如下: 135 | ``` 136 | const uint32_t rf_chan24g_20m[] = { 137 | 138 | // chan freq reg int frac 139 | 0x2A203, 0x43333, // 1 2412 0xA2033333 40 0x33333 140 | 0x2A204, 0x48888, // 2 2417 0xA2048888 40 0x48888 141 | 0x2A205, 0x4DDDD, // 3 2422 0xA205DDDD 40 0x5DDDD 142 | 0x2A207, 0x43333, // 4 2427 0xA2073333 40 0x73333 143 | 0x2A208, 0x48888, // 5 2432 0xA2088888 40 0x88888 144 | 0x2A209, 0x4DDDD, // 6 2437 0xA209DDDD 40 0x9DDDD 145 | 0x2A20B, 0x43333, // 7 2442 0xA20B3333 40 0xB3333 146 | 0x2A20C, 0x48888, // 8 2447 0xA20C8888 40 0xC8888 147 | 0x2A20D, 0x4DDDD, // 9 2452 0xA20DDDDD 40 0xDDDDD 148 | 0x2A20F, 0x43333, // 10 2457 0xA20F3333 40 0xF3333 149 | 0x2A600, 0x48888, // 11 2462 0xA6008888 41 0x08888 150 | 0x2A601, 0x4DDDD, // 12 2467 0xA601DDDD 41 0x1DDDD 151 | 0x2A603, 0x43333, // 13 2472 0xA6033333 41 0x33333 152 | 0x2A606, 0x46666, // 14 2484 0xA6066666 41 0x66666 153 | } 154 | ``` 155 | 156 | 这里的推导过程省略,主要是观察到 1.在2457-2462之间发生了进位 2. 在1-10频道中每次增加的小数分频值代表5MHz 157 | 最终得出 W60x 的频率合成器计算公式为 158 | ``` 159 | F = 60 MHz * (int + frac/0xFFFFF) 160 | ``` 161 | 并且该寄存器的结构为 162 | ``` 163 | 6'b + 6'b + 20'b 164 | ``` 165 | 最后作为老缝合怪,可以在 arduino 环境中糊出一堆勉强能用的测试代码 166 | 在我的这块 TB-01 开发板上,频率范围在 2161MHz~2931MHz 之间调节时,频谱都没有出现明显不对劲(PLL锁上了大概 167 | 但射频性能在 Wi-Fi 频段以外会明显劣化,故不建议使用偏移过远的中心频率 168 | ``` 169 | // Notice that 'extern "C"' 170 | extern "C" { 171 | #include 172 | #include 173 | } 174 | 175 | void _rf_spi_w(int arg) 176 | { 177 | *((uint32_t*)0x40011408) = arg << 10; 178 | delayMicroseconds(1); 179 | *((uint32_t*)0x40011400) = 1; 180 | while(*((uint32_t*)0x40011404) & 0x40000); 181 | delayMicroseconds(1); 182 | return; 183 | } 184 | 185 | void w60x_set_center_frequency_20mbw(uint32_t freq_mhz) 186 | { 187 | uint32_t spi_reg1, spi_reg2, reg_synth; 188 | uint32_t chan_div_int, chan_div_frac; 189 | uint32_t cpu_sr; 190 | 191 | chan_div_int = 0x0000003F & (freq_mhz/60); 192 | chan_div_frac = 0x000FFFFF & ( ((freq_mhz-(chan_div_int*60)) * (0xFFFFF)) / 60 ); 193 | 194 | reg_synth = 0x02000000 | (chan_div_int << 26) | (chan_div_frac); 195 | spi_reg1 = 0x00020000 | (reg_synth >> 16); 196 | spi_reg2 = 0x00040000 | (reg_synth & 0x0000FFFF); 197 | 198 | _rf_spi_w(spi_reg1); 199 | _rf_spi_w(spi_reg2); 200 | 201 | // wm_rf_band_switch @20MHz BW 202 | _rf_spi_w(0x102640); //write(0x8, 0x2640) 203 | _rf_spi_w(0x146967); //write(0xA, 0x6967) 204 | _rf_spi_w(0x102641); //write(0x8, 0x2641) 205 | delayMicroseconds(180); 206 | _rf_spi_w(0x102740); //write(0x8, 0x2740) 207 | _rf_spi_w(0x145327); //write(0xA, 0x5327) 208 | _rf_spi_w(0x102741); //write(0x8, 0x2741) 209 | delayMicroseconds(180); 210 | _rf_spi_w(0x1027C1); //write(0x8, 0x27C1) 211 | _rf_spi_w(0x10CDC0); //write(0x8, 0xCDC0) 212 | // end of wm_rf_band_switch @20MHz BW 213 | 214 | // I don't know what's 0x40001400 controls 215 | cpu_sr = tls_os_set_critical(); 216 | *((uint32_t*)0x40001400) = *((uint32_t*)0x40001400) & 0xFFFFFFDF; 217 | tls_os_release_critical(cpu_sr); 218 | 219 | return; 220 | } 221 | 222 | ``` 223 | -------------------------------------------------------------------------------- /rf-channel-bandwidth.md: -------------------------------------------------------------------------------- 1 | # 关于 5MHz/10MHz 带宽 2 | W60X 传输时占用的频宽可以通过调节 WLAN 系统根时钟分频系数来改变。 3 | 蛋疼的事是APB时钟又从这个时钟分频而来,改变这里的时钟会导致APB下面挂的所有设备跟着改变; 4 | 即,假如写了 Serial.begin(230400); 又写了 w60x_set_wlan_channel_bw(10); 那串口实际只有 115200。 5 | 关于更改时钟分频系数的部分,寄存器手册里说得比较清楚, 直接上代码: 6 | ``` 7 | // usable bw_mhz: 20(default), 10, 5 8 | // note1: this func assume cpu is running at 80MHz 9 | // note2: this func affect all devices' clock under APB 10 | // (e.g. set channel bw to 10MHz & set UART to 115200 ==> you'll get a 57600 UART) 11 | void w60x_set_wlan_channel_bw(uint32_t bw_mhz) 12 | { 13 | uint32_t reg, clk_mhz; 14 | uint8_t wlan_div, bus2_factor; 15 | 16 | reg = *((uint32_t*)0x40000710); 17 | clk_mhz = bw_mhz * 8; 18 | 19 | switch(clk_mhz) { 20 | case 80: 21 | wlan_div = 2; 22 | bus2_factor = 4; 23 | break; 24 | case 40: 25 | wlan_div = 4; 26 | bus2_factor = 8; 27 | break; 28 | default: // 160mhz 29 | wlan_div = 1; 30 | bus2_factor = 2; 31 | break; 32 | } 33 | 34 | reg &= ~(0x00000FF0); 35 | reg |= (wlan_div <<4); 36 | reg |= (bus2_factor <<8); 37 | 38 | *((uint32_t*)0x40000710) = reg; 39 | delayMicroseconds(1); 40 | *((uint32_t*)0x40000710) = reg | 0x80000000; 41 | delayMicroseconds(1); 42 | 43 | return; 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /screenshots/20201101140901.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libc0607/w60x-rf-hacking/f2efe9ce291aa4ed37e69c99e9e939c995b5b66f/screenshots/20201101140901.jpg -------------------------------------------------------------------------------- /screenshots/20201101141230.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libc0607/w60x-rf-hacking/f2efe9ce291aa4ed37e69c99e9e939c995b5b66f/screenshots/20201101141230.jpg -------------------------------------------------------------------------------- /screenshots/20201101141251.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libc0607/w60x-rf-hacking/f2efe9ce291aa4ed37e69c99e9e939c995b5b66f/screenshots/20201101141251.jpg -------------------------------------------------------------------------------- /screenshots/20201101141313.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libc0607/w60x-rf-hacking/f2efe9ce291aa4ed37e69c99e9e939c995b5b66f/screenshots/20201101141313.jpg -------------------------------------------------------------------------------- /screenshots/20201101144440.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libc0607/w60x-rf-hacking/f2efe9ce291aa4ed37e69c99e9e939c995b5b66f/screenshots/20201101144440.jpg -------------------------------------------------------------------------------- /screenshots/20201101145004.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libc0607/w60x-rf-hacking/f2efe9ce291aa4ed37e69c99e9e939c995b5b66f/screenshots/20201101145004.jpg -------------------------------------------------------------------------------- /screenshots/20201103143319.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libc0607/w60x-rf-hacking/f2efe9ce291aa4ed37e69c99e9e939c995b5b66f/screenshots/20201103143319.png -------------------------------------------------------------------------------- /w60x-rf-hack/w60x-rf-hack.ino: -------------------------------------------------------------------------------- 1 | /* 2 | WinnerMicro W600 Wi-Fi Center Frequency Hacking Demo 3 | 4 | Github @libc0607 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | extern "C" { 11 | #include 12 | #include 13 | } 14 | 15 | #define LED_PIN PB_14 16 | 17 | uint8_t send_data[] = { 18 | // rts header 19 | 0xb4, 0x01, 20 | 0x00, 0x00, 21 | 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 22 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 23 | // custom payload 24 | 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 25 | 0xde, 0xad, 0xbe, 0xef 26 | }; 27 | 28 | // usable bw_mhz: 20(default), 10, 5 29 | // note1: this func assume cpu is running at 80MHz 30 | // note2: this func affect all devices' clock under APB 31 | // (e.g. set channel bw to 10MHz & set UART to 115200 ==> you'll get a 57600 UART) 32 | void w60x_set_wlan_channel_bw(uint32_t bw_mhz) 33 | { 34 | uint32_t reg, clk_mhz; 35 | uint8_t wlan_div, bus2_factor; 36 | 37 | reg = *((uint32_t*)0x40000710); 38 | clk_mhz = bw_mhz * 8; 39 | 40 | switch(clk_mhz) { 41 | case 80: 42 | wlan_div = 2; 43 | bus2_factor = 4; 44 | break; 45 | case 40: 46 | wlan_div = 4; 47 | bus2_factor = 8; 48 | break; 49 | default: // 160mhz 50 | wlan_div = 1; 51 | bus2_factor = 2; 52 | break; 53 | } 54 | 55 | reg &= ~(0x00000FF0); 56 | reg |= (wlan_div <<4); 57 | reg |= (bus2_factor <<8); 58 | 59 | *((uint32_t*)0x40000710) = reg; 60 | delayMicroseconds(1); 61 | *((uint32_t*)0x40000710) = reg | 0x80000000; 62 | delayMicroseconds(1); 63 | 64 | return; 65 | } 66 | 67 | // arg: 10'b + 5'b + 1'b + 16'b 68 | void _rf_spi_w(int arg) 69 | { 70 | *((uint32_t*)0x40011408) = arg << 10; 71 | delayMicroseconds(1); 72 | *((uint32_t*)0x40011400) = 1; 73 | while(*((uint32_t*)0x40011404) & 0x40000); 74 | delayMicroseconds(1); 75 | return; 76 | } 77 | 78 | void w60x_set_center_frequency_20mbw(uint32_t freq_mhz) 79 | { 80 | uint32_t spi_reg1, spi_reg2, reg_synth; 81 | uint32_t chan_div_int, chan_div_frac; 82 | uint32_t cpu_sr; 83 | 84 | chan_div_int = 0x0000003F & (freq_mhz/60); 85 | chan_div_frac = 0x000FFFFF & ( ((freq_mhz-(chan_div_int*60)) * (0xFFFFF)) / 60 ); 86 | 87 | reg_synth = 0x02000000 | (chan_div_int << 26) | (chan_div_frac); 88 | spi_reg1 = 0x00020000 | (reg_synth >> 16); 89 | spi_reg2 = 0x00040000 | (reg_synth & 0x0000FFFF); 90 | 91 | _rf_spi_w(spi_reg1); 92 | _rf_spi_w(spi_reg2); 93 | 94 | // wm_rf_band_switch @20MHz BW 95 | _rf_spi_w(0x102640); //write(0x8, 0x2640) 96 | _rf_spi_w(0x146967); //write(0xA, 0x6967) 97 | _rf_spi_w(0x102641); //write(0x8, 0x2641) 98 | delayMicroseconds(180); 99 | _rf_spi_w(0x102740); //write(0x8, 0x2740) 100 | _rf_spi_w(0x145327); //write(0xA, 0x5327) 101 | _rf_spi_w(0x102741); //write(0x8, 0x2741) 102 | delayMicroseconds(180); 103 | _rf_spi_w(0x1027C1); //write(0x8, 0x27C1) 104 | _rf_spi_w(0x10CDC0); //write(0x8, 0xCDC0) 105 | // end of wm_rf_band_switch @20MHz BW 106 | 107 | // I don't know what's 0x40001400 controls 108 | cpu_sr = tls_os_set_critical(); 109 | *((uint32_t*)0x40001400) = *((uint32_t*)0x40001400) & 0xFFFFFFDF; 110 | tls_os_release_critical(cpu_sr); 111 | 112 | return; 113 | } 114 | 115 | void setup() { 116 | Serial.begin(115200); // Initialize the UART0 TX PA4 RX PA5 117 | Serial.println("Demo Start"); 118 | pinMode(LED_PIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output 119 | 120 | 121 | tls_wifi_change_chanel(0); 122 | w60x_set_wlan_channel_bw(10); 123 | w60x_set_center_frequency_20mbw(freq); 124 | } 125 | 126 | uint32_t freq = 2312; 127 | 128 | void loop() { 129 | tls_wifi_tx_rate_t rate_t; 130 | rate_t.tx_rate = WM_WIFI_TX_RATEIDX_6M; 131 | rate_t.tx_gain = tls_wifi_get_tx_gain_max(rate_t.tx_rate); 132 | for (int i=0; i<1000; i++) { 133 | tls_wifi_send_data(NULL, send_data, sizeof(send_data), &rate_t); 134 | delayMicroseconds(1); 135 | } 136 | 137 | freq++; 138 | if (freq > 2712) 139 | freq = 2312; 140 | 141 | w60x_set_center_frequency_20mbw(freq); 142 | Serial.println(freq); 143 | } 144 | -------------------------------------------------------------------------------- /w60x-rf-rx/w60x-rf-rx.ino: -------------------------------------------------------------------------------- 1 | // Github @libc0607 2 | 3 | #include 4 | #include 5 | extern "C" { 6 | #include 7 | #include 8 | } 9 | 10 | #define LED_PIN PB_14 11 | 12 | uint8_t packet_counter = 0; 13 | 14 | tls_wifi_tx_rate_t rate_t; 15 | uint32_t freq_hopping_list[8] = {2170, 2270, 2370, 2470, 2570, 2670, 2770, 2870}; 16 | 17 | void _rf_spi_w(int arg) 18 | { 19 | *((uint32_t*)0x40011408) = arg << 10; 20 | delayMicroseconds(1); 21 | *((uint32_t*)0x40011400) = 1; 22 | while(*((uint32_t*)0x40011404) & 0x40000); 23 | delayMicroseconds(1); 24 | return; 25 | } 26 | 27 | void w60x_set_center_frequency_20mbw(uint32_t freq_mhz) 28 | { 29 | uint32_t spi_reg1, spi_reg2, reg_synth; 30 | uint32_t chan_div_int, chan_div_frac; 31 | uint32_t cpu_sr; 32 | 33 | chan_div_int = 0x0000003F & (freq_mhz/60); 34 | chan_div_frac = 0x000FFFFF & ( ((freq_mhz-(chan_div_int*60)) * (0xFFFFF)) / 60 ); 35 | 36 | reg_synth = 0x02000000 | (chan_div_int << 26) | (chan_div_frac); 37 | spi_reg1 = 0x00020000 | (reg_synth >> 16); 38 | spi_reg2 = 0x00040000 | (reg_synth & 0x0000FFFF); 39 | 40 | _rf_spi_w(spi_reg1); 41 | _rf_spi_w(spi_reg2); 42 | 43 | // wm_rf_band_switch @20MHz BW 44 | _rf_spi_w(0x102640); //write(0x8, 0x2640) 45 | _rf_spi_w(0x146967); //write(0xA, 0x6967) 46 | _rf_spi_w(0x102641); //write(0x8, 0x2641) 47 | delayMicroseconds(180); 48 | _rf_spi_w(0x102740); //write(0x8, 0x2740) 49 | _rf_spi_w(0x145327); //write(0xA, 0x5327) 50 | _rf_spi_w(0x102741); //write(0x8, 0x2741) 51 | delayMicroseconds(180); 52 | _rf_spi_w(0x1027C1); //write(0x8, 0x27C1) 53 | _rf_spi_w(0x10CDC0); //write(0x8, 0xCDC0) 54 | // end of wm_rf_band_switch @20MHz BW 55 | 56 | // I don't know what's 0x40001400 controls 57 | cpu_sr = tls_os_set_critical(); 58 | *((uint32_t*)0x40001400) = *((uint32_t*)0x40001400) & 0xFFFFFFDF; 59 | tls_os_release_critical(cpu_sr); 60 | 61 | return; 62 | } 63 | 64 | void w60x_set_wlan_channel_bw(uint32_t bw_mhz) 65 | { 66 | uint32_t reg, clk_mhz; 67 | uint8_t wlan_div, bus2_factor; 68 | 69 | reg = *((uint32_t*)0x40000710); 70 | clk_mhz = bw_mhz * 8; 71 | 72 | switch(clk_mhz) { 73 | case 80: 74 | wlan_div = 2; 75 | bus2_factor = 4; 76 | break; 77 | case 40: 78 | wlan_div = 4; 79 | bus2_factor = 8; 80 | break; 81 | default: // 160mhz 82 | wlan_div = 1; 83 | bus2_factor = 2; 84 | break; 85 | } 86 | 87 | reg &= ~(0x00000FF0); 88 | reg |= (wlan_div <<4); 89 | reg |= (bus2_factor <<8); 90 | 91 | Serial.println(reg); 92 | 93 | *((uint32_t*)0x40000710) = reg; 94 | delayMicroseconds(1); 95 | *((uint32_t*)0x40000710) = reg | 0x80000000; 96 | delayMicroseconds(1); 97 | 98 | return; 99 | } 100 | 101 | 102 | // custom packet using rts header: 103 | /* 104 | uint8_t ieee_packet_rts[] = { 105 | // rts header 106 | 0xb4, 0x01, 107 | 0x00, 0x00, 108 | 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 109 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 110 | // custom payload 111 | 0xde, 0xad, 0xbe, 0xef, // offset: 0x10, 0x11, 0x12, 0x13 112 | 0xXX, 0x00, 0x00, 0x00, // offset: 0x14, 0x15, 0x16, 0x17 113 | }; 114 | */ 115 | 116 | static void recv_cb (u8 *dat, u32 len) 117 | { 118 | if (dat[16] == 0xde && dat[17] == 0xad) { 119 | // we got packet 120 | packet_counter = dat[20]; 121 | packet_counter++; 122 | 123 | // write next frequency 124 | w60x_set_center_frequency_20mbw(freq_hopping_list[packet_counter%8]); 125 | 126 | Serial.println(dat[20]); 127 | digitalWrite(LED_PIN, digitalRead(LED_PIN) == LOW? HIGH: LOW); 128 | 129 | } 130 | } 131 | 132 | 133 | void setup() { 134 | Serial.begin(230400); // Initialize the UART0 TX PA4 RX PA5 135 | Serial.println("Demo Start"); 136 | pinMode(LED_PIN, OUTPUT); 137 | digitalWrite(LED_PIN, HIGH); 138 | 139 | // set monitor & center frequency 140 | tls_wifi_change_chanel(0); 141 | w60x_set_wlan_channel_bw(10); 142 | w60x_set_center_frequency_20mbw(2370); 143 | tls_wifi_set_listen_mode(1); 144 | 145 | tls_wifi_data_recv_cb_register(recv_cb); 146 | } 147 | 148 | void loop() { 149 | // nothing to do 150 | } 151 | -------------------------------------------------------------------------------- /w60x-rf-tx/w60x-rf-tx.ino: -------------------------------------------------------------------------------- 1 | // Github @libc0607 2 | 3 | #include 4 | #include 5 | extern "C" { 6 | #include 7 | #include 8 | } 9 | 10 | #define LED_PIN PB_14 11 | 12 | uint8_t packet_counter = 0; 13 | tls_wifi_tx_rate_t rate_t; 14 | uint32_t freq_hopping_list[8] = {2170, 2270, 2370, 2470, 2570, 2670, 2770, 2870}; 15 | 16 | uint8_t ieee_packet_rts[] = { 17 | // rts header 18 | 0xb4, 0x01, 19 | 0x00, 0x00, 20 | 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 21 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 22 | // custom payload 23 | 0xde, 0xad, 0xbe, 0xef, 24 | 0x00, 0x00, 0x00, 0x00, 25 | }; 26 | 27 | void _rf_spi_w(int arg) 28 | { 29 | *((uint32_t*)0x40011408) = arg << 10; 30 | delayMicroseconds(1); 31 | *((uint32_t*)0x40011400) = 1; 32 | while(*((uint32_t*)0x40011404) & 0x40000); 33 | delayMicroseconds(1); 34 | return; 35 | } 36 | 37 | void w60x_set_center_frequency_20mbw(uint32_t freq_mhz) 38 | { 39 | uint32_t spi_reg1, spi_reg2, reg_synth; 40 | uint32_t chan_div_int, chan_div_frac; 41 | uint32_t cpu_sr; 42 | 43 | chan_div_int = 0x0000003F & (freq_mhz/60); 44 | chan_div_frac = 0x000FFFFF & ( ((freq_mhz-(chan_div_int*60)) * (0xFFFFF)) / 60 ); 45 | 46 | reg_synth = 0x02000000 | (chan_div_int << 26) | (chan_div_frac); 47 | spi_reg1 = 0x00020000 | (reg_synth >> 16); 48 | spi_reg2 = 0x00040000 | (reg_synth & 0x0000FFFF); 49 | 50 | _rf_spi_w(spi_reg1); 51 | _rf_spi_w(spi_reg2); 52 | 53 | // wm_rf_band_switch @20MHz BW 54 | _rf_spi_w(0x102640); //write(0x8, 0x2640) 55 | _rf_spi_w(0x146967); //write(0xA, 0x6967) 56 | _rf_spi_w(0x102641); //write(0x8, 0x2641) 57 | delayMicroseconds(180); 58 | _rf_spi_w(0x102740); //write(0x8, 0x2740) 59 | _rf_spi_w(0x145327); //write(0xA, 0x5327) 60 | _rf_spi_w(0x102741); //write(0x8, 0x2741) 61 | delayMicroseconds(180); 62 | _rf_spi_w(0x1027C1); //write(0x8, 0x27C1) 63 | _rf_spi_w(0x10CDC0); //write(0x8, 0xCDC0) 64 | // end of wm_rf_band_switch @20MHz BW 65 | 66 | // I don't know what's 0x40001400 controls 67 | cpu_sr = tls_os_set_critical(); 68 | *((uint32_t*)0x40001400) = *((uint32_t*)0x40001400) & 0xFFFFFFDF; 69 | tls_os_release_critical(cpu_sr); 70 | 71 | return; 72 | } 73 | 74 | void w60x_set_wlan_channel_bw(uint32_t bw_mhz) 75 | { 76 | uint32_t reg, clk_mhz; 77 | uint8_t wlan_div, bus2_factor; 78 | 79 | reg = *((uint32_t*)0x40000710); 80 | clk_mhz = bw_mhz * 8; 81 | 82 | switch(clk_mhz) { 83 | case 80: 84 | wlan_div = 2; 85 | bus2_factor = 4; 86 | break; 87 | case 40: 88 | wlan_div = 4; 89 | bus2_factor = 8; 90 | break; 91 | default: // 160mhz 92 | wlan_div = 1; 93 | bus2_factor = 2; 94 | break; 95 | } 96 | 97 | reg &= ~(0x00000FF0); 98 | reg |= (wlan_div <<4); 99 | reg |= (bus2_factor <<8); 100 | 101 | Serial.println(reg); 102 | 103 | *((uint32_t*)0x40000710) = reg; 104 | delayMicroseconds(1); 105 | *((uint32_t*)0x40000710) = reg | 0x80000000; 106 | delayMicroseconds(1); 107 | 108 | return; 109 | } 110 | 111 | void setup() { 112 | Serial.begin(230400); // Initialize the UART0 TX PA4 RX PA5 113 | Serial.println("Demo Start"); 114 | pinMode(LED_PIN, OUTPUT); 115 | digitalWrite(LED_PIN, HIGH); 116 | 117 | tls_wifi_change_chanel(0); 118 | w60x_set_wlan_channel_bw(10); 119 | //w60x_set_center_frequency_20mbw(2312); 120 | rate_t.tx_rate = WM_WIFI_TX_RATEIDX_6M; 121 | rate_t.tx_gain = tls_wifi_get_tx_gain_max(rate_t.tx_rate); 122 | } 123 | 124 | void loop() { 125 | packet_counter++; 126 | Serial.println(packet_counter); 127 | 128 | w60x_set_center_frequency_20mbw(freq_hopping_list[packet_counter%8]); 129 | delay(1); 130 | 131 | ieee_packet_rts[sizeof(ieee_packet_rts)-4] = packet_counter; 132 | tls_wifi_send_data(NULL, ieee_packet_rts, sizeof(ieee_packet_rts), &rate_t); 133 | 134 | digitalWrite(LED_PIN, digitalRead(LED_PIN) == LOW? HIGH: LOW); 135 | delay(100); 136 | } 137 | --------------------------------------------------------------------------------