├── 50bee.png ├── LICENSE ├── README.md ├── helpers ├── 5ohBee.tar.gz ├── 99-USBasp.rules └── SmartResponseXE-lib.zip └── sketch ├── HugQuest.ino ├── RadioFunctions.h ├── SmartResponseXE.h ├── five-oh-BEE.ino ├── hexdump.ino ├── multi-chat.ino ├── multi-mode.ino ├── quest.ino └── rssi.ino /50bee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdxbadgers/5ohBEE-2019/f2a227239b3fc3d9156bea2e8e7e3a9396c39c47/50bee.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 5ohBEE bee art by https://github.com/ivycraft 2 | ====== 3 | 4 | Setting up your Board 5 | --------------------- 6 | 1. udev rules: copy helpers/99-USBasp.rules to /etc/udev/rules.d/ (this assumes you are using the USBasp programmer, update your IDE accordingly) 7 | 2. Add the board to Arduino IDE: Unzip helpers/5ohBee.tar.gz in your Arduino sketch directory, restart the IDE, and set your board to "ATmega128RFA1 Dev Board" (under "Sparkfun AVR Boards") 8 | 3. Install dependencies: In the IDE, select "Sketch" -> "Include Library" -> "Add .ZIP Library..." to add helpers/SmartResponseXE-lib.zip to the project 9 | 4. ??? 10 | 5. Profit! Add the contents of the sketch directory to your workspace, compile, and upload! 11 | 12 | Keymap 13 | ------ 14 | The keymap is documented on lines 64 - 90 of SmartResponseXE/blob/master/SmartResponseXE.cpp. Brief hints below: 15 | 16 | Most of the ASCII-printable range is mapped. 17 | 18 | Function and Special Keys: 19 | - Left Column: 0xF0 - 0xF4 (Top to bottom) 20 | - Right Column: 0xF5 - 0xF9 (Top to bottom) 21 | - Left: 0x02 22 | - Right: 0x03 23 | - Up: 0x04 24 | - Down: 0x05 25 | - Menu: 0x01 26 | 27 | Unmapped Sym Combos: 28 | - Sym+2 29 | - Sym+3 30 | - Sym+6 31 | - Sym+Z 32 | - Sym+X 33 | - Sym+M 34 | - Sym+N 35 | -------------------------------------------------------------------------------- /helpers/5ohBee.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdxbadgers/5ohBEE-2019/f2a227239b3fc3d9156bea2e8e7e3a9396c39c47/helpers/5ohBee.tar.gz -------------------------------------------------------------------------------- /helpers/99-USBasp.rules: -------------------------------------------------------------------------------- 1 | # USBasp - USB programmer for Atmel AVR controllers 2 | # Copy this file to /etc/udev/rules.d so 3 | 4 | # According to http://www.ladyada.net/make/usbtinyisp/avrdude.html 5 | # The udev examples given don't work on some systems as the SYSFS parameter is deprecated. 6 | # The following rule works on recent Ubuntu systems and should probably work on other newer Linux systems: 7 | SUBSYSTEM=="usb", ATTR{product}=="USBasp", ATTR{idProduct}=="05dc", ATTRS{idVendor}=="16c0", MODE="0666" 8 | -------------------------------------------------------------------------------- /helpers/SmartResponseXE-lib.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pdxbadgers/5ohBEE-2019/f2a227239b3fc3d9156bea2e8e7e3a9396c39c47/helpers/SmartResponseXE-lib.zip -------------------------------------------------------------------------------- /sketch/HugQuest.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include "RadioFunctions.h" 3 | #include 4 | #include 5 | 6 | char version[20]="HugQuest v1.5"; 7 | char messages[6][26]; 8 | char command[32] = "> \x00R05e\x00"; 9 | char netbuff[26] = ""; 10 | unsigned int curs = 2; 11 | int ncurs = 0; 12 | int row=0; 13 | uint8_t canaryOffset = 27; 14 | 15 | uint8_t rssi[32]; // yeah, what of it? 16 | 17 | unsigned long int time_loop=0; 18 | unsigned long int tokens=0; 19 | 20 | int infected=false; 21 | char outbuff[26]; 22 | 23 | // Operation mode constants 24 | #define CONST_MODE_CONSOLE 0 25 | #define CONST_MODE_HEX 1 26 | #define CONST_MODE_RSSI 2 27 | #define CONST_MODE_CHAT 3 28 | 29 | // Special keyboard constants 30 | #define CONST_KEY_CLEAR 0xF8 31 | #define CONST_KEY_EXIT 0xF9 32 | 33 | // EEPROM constants 34 | #define CONST_MEM_NAME 0x0000000 35 | #define CONST_MEM_HUGS 0x0000100 36 | #define CONST_MEM_HACK 0x0000200 37 | 38 | struct global_t{ 39 | int mode = CONST_MODE_CONSOLE; 40 | char command[26] = "> "; 41 | char canary[5] = "R05e"; 42 | uint8_t name[256]; 43 | uint16_t hexdumpaddr; 44 | uint32_t rfChannel; 45 | uint8_t rows; // screen rows 46 | uint8_t columns; // screen columns 47 | } global; 48 | 49 | void reset(){ 50 | EEPROM.write(CONST_MEM_NAME,0xFF); 51 | getName(); 52 | } 53 | 54 | void setup() { 55 | // put your setup code here, to run once: 56 | SRXEInit(0xe7, 0xd6, 0xa2); // initialize display 57 | SRXEWriteString(0,120,global.command, FONT_LARGE, 3, 0); // draw large black text at x=0,y=120, fg=3, bg=0 58 | global.rows = 6; 59 | 60 | for(int i = 0; i < global.rows; i++){ 61 | strncpy(messages[i], " ",24); 62 | } 63 | resetInputBuffer(); 64 | global.mode = CONST_MODE_CONSOLE; 65 | global.rfChannel = 11; 66 | rfBegin(global.rfChannel); 67 | 68 | // set up the watchdog timer 69 | wdt_enable(WDTO_8S); 70 | 71 | // set up the name in memory 72 | if(getName()) 73 | { 74 | 75 | if(infected) 76 | { 77 | omghax(); 78 | return; 79 | } 80 | snprintf(outbuff,24,"Welcome back %s!",global.name); 81 | submit(outbuff); 82 | 83 | snprintf(outbuff,24,"You have %lu HUG tokens.",tokens); 84 | submit(outbuff); 85 | submit("Press % or > to submit."); 86 | } 87 | } 88 | 89 | void clearScreen(){ 90 | for(int i = 0; i < global.rows; i++){ submit(" "); } 91 | row = 0; 92 | } 93 | 94 | int getName() 95 | { 96 | // flash is totally empty, welcome the new user! 97 | if(EEPROM.read(CONST_MEM_NAME)==255) 98 | { 99 | clearScreen(); 100 | submit(version); 101 | submit("What is your name?"); 102 | submit("type 'set name '"); 103 | submit("Press % or > to submit."); 104 | 105 | EEPROM.put(CONST_MEM_HUGS,(unsigned long)0); 106 | EEPROM.put(CONST_MEM_HACK,(int)0); 107 | return false; 108 | } 109 | 110 | // how many tokens we got? 111 | EEPROM.get(CONST_MEM_HUGS,tokens); 112 | EEPROM.get(CONST_MEM_HACK,infected); 113 | 114 | for(int i = 0; i < 4; i++) 115 | { 116 | char nameByte = EEPROM.read(CONST_MEM_NAME+i); 117 | //snprintf(outbuff,20,"%d %02x %03d : %c",i,nameByte,nameByte,nameByte); 118 | //submit(outbuff); 119 | 120 | if(nameByte >= 0x20 && nameByte <= 0x7A) 121 | { 122 | global.name[i] = nameByte; 123 | //break; 124 | } 125 | else 126 | { 127 | global.name[i] = 0x00; 128 | } 129 | } 130 | global.name[4]=0; 131 | 132 | return true; 133 | } 134 | 135 | int setName(char *name) 136 | { 137 | if(strlen(name)<=0||strlen(name)>3) 138 | { 139 | submit("NAME MUST BE 1-3 CHARS!"); 140 | return false; 141 | } 142 | 143 | for(int i = 0; i < 4; i++) 144 | { 145 | EEPROM.write(CONST_MEM_NAME+i,name[i]); 146 | global.name[i]=name[i]; 147 | if(name[i] == 0x00) 148 | { 149 | break; 150 | } 151 | } 152 | 153 | return true; 154 | } 155 | 156 | void resetInputBuffer() 157 | { 158 | memcpy(global.command, "> ",26); 159 | curs = 2; 160 | SRXEWriteString(0,120,global.command, FONT_LARGE, 3, 0); 161 | } 162 | 163 | void redraw() 164 | { 165 | SRXEWriteString(0,0 ," ", FONT_LARGE, 3, 0); 166 | SRXEWriteString(0,20 ," ", FONT_LARGE, 3, 0); 167 | SRXEWriteString(0,40 ," ", FONT_LARGE, 3, 0); 168 | SRXEWriteString(0,60 ," ", FONT_LARGE, 3, 0); 169 | SRXEWriteString(0,80 ," ", FONT_LARGE, 3, 0); 170 | SRXEWriteString(0,100," ", FONT_LARGE, 3, 0); 171 | 172 | SRXEWriteString(0,0 ,messages[(0+row)%global.rows], FONT_LARGE, 3, 0); 173 | SRXEWriteString(0,20 ,messages[(1+row)%global.rows], FONT_LARGE, 3, 0); 174 | SRXEWriteString(0,40 ,messages[(2+row)%global.rows], FONT_LARGE, 3, 0); 175 | SRXEWriteString(0,60 ,messages[(3+row)%global.rows], FONT_LARGE, 3, 0); 176 | SRXEWriteString(0,80 ,messages[(4+row)%global.rows], FONT_LARGE, 3, 0); 177 | SRXEWriteString(0,100,messages[(5+row)%global.rows], FONT_LARGE, 3, 0); 178 | } 179 | 180 | void handleInput(char* cmd) 181 | { 182 | if(!memcmp(cmd,"set",3)) 183 | { 184 | char* item = strtok(cmd," "); 185 | if(item){ 186 | item = strtok(NULL," "); 187 | if(item){ 188 | if(!memcmp(item,"name",4)) 189 | { 190 | item = strtok(NULL," "); 191 | if(setName(item)) 192 | { 193 | snprintf(outbuff,24,"Hello '%s', welcome!",item); 194 | submit(outbuff); 195 | } 196 | //getName(); 197 | } 198 | else if(!memcmp(item,"channel",7)) 199 | { 200 | item = strtok(NULL," "); 201 | int newchan=atoi(item); 202 | if(newchan>=11 && newchan<=26) 203 | { 204 | global.rfChannel = newchan; 205 | rfBegin(global.rfChannel); 206 | 207 | snprintf(outbuff,24,"Radio on channel %d",global.rfChannel); 208 | submit(outbuff); 209 | } 210 | else 211 | { 212 | submit("Channel must be 11-26"); 213 | } 214 | } 215 | else if(!memcmp(item,"tokens",6)) 216 | { 217 | submit("No."); 218 | } 219 | else{ 220 | submit("Set what? name channel"); 221 | } 222 | }else{ 223 | submit("Set what? name channel"); 224 | } 225 | } 226 | }else if(!memcmp(cmd,"get",3)){ 227 | char* item = strtok(cmd," "); 228 | if(item){ 229 | item = strtok(NULL, " "); 230 | if(item){ 231 | if(!memcmp(item,"name",4)) 232 | { 233 | getName(); 234 | submit((char*)global.name); 235 | } 236 | else if(!memcmp(item,"timer",5)) 237 | { 238 | snprintf(outbuff,20,"Timer is at %lu",time_loop); 239 | submit(outbuff); 240 | } 241 | else if(!memcmp(item,"channel",7)) 242 | { 243 | snprintf(outbuff,20,"Radio on channel %d",global.rfChannel); 244 | submit(outbuff); 245 | } 246 | else if(!memcmp(item,"tokens",6)) 247 | { 248 | snprintf(outbuff,24,"You have %lu HUG tokens.",tokens); 249 | submit(outbuff); 250 | } 251 | 252 | else 253 | { 254 | submit("Get what?"); 255 | submit("name channel tokens"); 256 | } 257 | }else{ 258 | submit("Get what?"); 259 | submit("name channel tokens"); 260 | } 261 | } 262 | }else if(!memcmp(cmd,"hex",3)){ 263 | global.mode = CONST_MODE_HEX; 264 | global.hexdumpaddr = 0; 265 | // fill the first 6 lines of the screen 266 | while(global.hexdumpaddr < (6*4)) 267 | { 268 | readHexLine(global.hexdumpaddr); 269 | global.hexdumpaddr += 4; 270 | } 271 | } 272 | else if(!memcmp(cmd,"rssi",4)) 273 | { 274 | for(int i=0;i<30;++i)rssi[i]=0; 275 | global.mode = CONST_MODE_RSSI; 276 | SRXEPowerDown(); 277 | SRXEPowerUp(); 278 | } 279 | else if(!memcmp(cmd,"help",4)) 280 | { 281 | submit("Basic commands:"); 282 | submit(" get set hug mine rssi"); 283 | if(tokens>=100) 284 | { 285 | submit(" also 'WANNAHUG'.."); 286 | } 287 | } 288 | else if(!memcmp(cmd,"resetforreals",13)){reset();} 289 | else if(!memcmp(cmd,"reset",5)){submit("Try 'resetforreals'");} 290 | else if(!memcmp(cmd,"version",7)){submit(version);} 291 | else if(!memcmp(cmd,"ascii",5)){ 292 | for(int x=0;x<256;++x) 293 | { 294 | snprintf(outbuff,20,"%02x %03d : %c",x,x,x); 295 | delay(1000); 296 | submit(outbuff); 297 | } 298 | } 299 | else if(!memcmp(cmd,"unlock",6)) 300 | { 301 | if(tokens>=10) 302 | { 303 | tokens-=10; 304 | infected=false; 305 | EEPROM.put(CONST_MEM_HACK,infected); 306 | EEPROM.put(CONST_MEM_HUGS,tokens); 307 | submit("SYSTEM UNLOCKED"); 308 | } 309 | else 310 | { 311 | submit("You need more HUGs"); 312 | } 313 | } 314 | else if(!memcmp(cmd,"mine",4)) 315 | { 316 | unsigned int mined = time_loop/10000; 317 | 318 | tokens = tokens+mined; 319 | EEPROM.put(CONST_MEM_HUGS,tokens); 320 | 321 | snprintf(outbuff,24,"Mined %u HUG tokens.",mined); 322 | submit(outbuff); 323 | } 324 | else if(!memcmp(cmd,"hug",3)) 325 | { 326 | rfWrite('h'); 327 | rfWrite('u'); 328 | rfWrite('g'); 329 | rfWrite('\n'); // write the last byte 330 | submit("Hug sent!!"); 331 | if(tokens>0) 332 | { 333 | tokens=tokens-1; 334 | EEPROM.put(CONST_MEM_HUGS,tokens); 335 | } 336 | } 337 | else if(!memcmp(cmd,"WANNAHUG",8)) 338 | { 339 | if(tokens<100) 340 | { 341 | submit("Who told you that cmd?"); 342 | return; 343 | } 344 | 345 | rfWrite('h'); 346 | rfWrite('a'); 347 | rfWrite('x'); 348 | rfWrite('\n'); // write the last byte 349 | submit("WANNAHUG sent!!"); 350 | } 351 | // doesn't look like a command, so let's blast it to the chat! 352 | else 353 | { 354 | // make sure they have their name set 355 | if(!getName())return; 356 | 357 | char outputbuff[26]; 358 | 359 | memset(outbuff,0,25); 360 | snprintf(outbuff,24,"%-3s:%s.",global.name,global.command+2); 361 | 362 | // transmit 363 | for(int i=0;i24)return false; 379 | 380 | memcpy(messages[row]," ",24); 381 | messages[row][24]=0; 382 | memcpy(messages[row],submission, 24); 383 | row = (row+1)%global.rows; 384 | redraw(); 385 | } 386 | 387 | void checkCanary() 388 | { 389 | //if(memcmp(command+canaryOffset,"R05e",4) != 0) { 390 | if(memcmp(global.canary,"R05e",4) != 0) { 391 | for(int i = 0; i < 6; i++){ strcpy(messages[i],"OMGH@XXE!"); } 392 | //redraw(); 393 | } 394 | } 395 | 396 | // readHexLine(uint32_t) 397 | // Read 4 bytes starting from the specified address and print it to the string formatted as: 398 | //
399 | void readHexLine(uint32_t addr) 400 | { 401 | byte foo[4]; 402 | char bar[26]; 403 | for(int j = 0; j < 4; j++){ foo[j] = EEPROM.read(addr+j); } 404 | snprintf(bar, 24, "%04x %02x%02x%02x%02x %c%c%c%c", addr, foo[0],foo[1],foo[2],foo[3], foo[0],foo[1],foo[2],foo[3]); 405 | bar[24] = 0x00; 406 | submit(bar); 407 | } 408 | 409 | void updateInputBuffer(byte k){ 410 | if(k >= 0x20 && k <= 0x7A){ 411 | //is it printable? 412 | if(curs <= 20) 413 | { 414 | global.command[curs]=k; 415 | curs++; 416 | } 417 | 418 | }else if(k == 0x08){ 419 | // backspace? 420 | if(curs > 2){ 421 | curs--; 422 | } 423 | global.command[curs] = 0x20; //space is your blank character 424 | } 425 | 426 | SRXEWriteString(0,120,global.command, FONT_LARGE, 3, 0); 427 | } 428 | 429 | // mode_hex_loop(byte) 430 | // This is the loop function for when the device is in hex-dump mode. 431 | // TODO: 432 | // - Enable reading backwards 433 | void mode_hex_loop(byte k){ 434 | if(k){ 435 | readHexLine(global.hexdumpaddr); 436 | if(global.hexdumpaddr <= (4*1024)) 437 | { 438 | global.hexdumpaddr += 4; 439 | } 440 | } 441 | } 442 | 443 | // mode_console_loop(byte) 444 | // This is the loop function for when the device is in console (default) mode 445 | void mode_console_loop(byte r, byte k){ 446 | 447 | if(r){ 448 | if(r=='\n') 449 | { 450 | // HERE IS WHERE WE ACCEPT COMMANDS FROM THE NETWORK 451 | if(!memcmp(netbuff,"hug",3)) 452 | { 453 | submit("OMG YOU'VE BEEN HUGGED!"); 454 | tokens=tokens+1; 455 | EEPROM.put(CONST_MEM_HUGS,tokens); 456 | } 457 | else if(!memcmp(netbuff,"hax",3)) 458 | { 459 | omghax(); 460 | infected=true; 461 | EEPROM.put(CONST_MEM_HACK,infected); 462 | } 463 | else submit(netbuff); 464 | strncpy(netbuff," ",24); 465 | ncurs = 0; 466 | } 467 | else 468 | { 469 | netbuff[ncurs]=r; 470 | ncurs = (ncurs+1)%24; 471 | } 472 | } 473 | 474 | 475 | if(k){ 476 | // submit on "return" (key right of 'Sym', box line box) 477 | if(k==0x0D || k==0x03) 478 | { 479 | if(curs>3) 480 | { 481 | if(infected==true) 482 | { 483 | // while infected, special case to unlock 484 | if(!memcmp(global.command+2,"unlock",6)) 485 | { 486 | handleInput(global.command+2); 487 | resetInputBuffer(); 488 | return; 489 | } 490 | 491 | omghax(); 492 | 493 | resetInputBuffer(); 494 | return; 495 | } 496 | 497 | handleInput(global.command+2); 498 | resetInputBuffer(); 499 | } 500 | }else{ 501 | //update input buffer 502 | updateInputBuffer(k); 503 | } 504 | } 505 | } 506 | 507 | void omghax() 508 | { 509 | clearScreen(); 510 | submit("YOU HAVE BEEN INFECTED"); 511 | submit("WITH ** WANNAHUG **"); 512 | submit("YOU MUST PAY 10 HUG"); 513 | snprintf(outbuff,24,"You have %lu HUG tokens.",tokens); 514 | submit(outbuff); 515 | submit("Type 'unlock' when ready"); 516 | } 517 | 518 | // mode_rssi_loop() 519 | // This is a port of earlier RSSI code 520 | void mode_rssi_loop(){ 521 | 522 | time_loop = 0; 523 | 524 | int x; 525 | int y; 526 | 527 | for(int i=11;i<=26;++i) 528 | { 529 | rfBegin(i); // change channel 530 | delay(100); 531 | 532 | y=(i-11)%8*17; 533 | if(i<19){ x = 0;} 534 | else { x = 201; } 535 | 536 | if(rfAvailable()) 537 | { 538 | while(0>rfRead()){} // burn through the reads 539 | rssi[i]+=rssiRaw; 540 | } 541 | 542 | snprintf(outbuff,24,"Ch %d : %d",i,rssi[i]); 543 | SRXEWriteString(x,y ,outbuff, FONT_LARGE, 3, 0); 544 | 545 | } 546 | // point out the "back" button 547 | SRXEWriteString(360,120 ,"back", FONT_SMALL, 3, 0); 548 | } 549 | 550 | void loop() { 551 | 552 | // reset the watchdog 553 | wdt_reset(); 554 | 555 | // increment the sleep timer 556 | time_loop+=1; 557 | if(time_loop>50000) // maybe a minute or so? 558 | { 559 | time_loop=0; 560 | wdt_disable(); 561 | SRXESleep(); 562 | wdt_enable(WDTO_8S); 563 | redraw(); 564 | resetInputBuffer(); 565 | } 566 | 567 | 568 | // if we hear something on the radio, build up the net buffer 569 | byte r = NULL; 570 | if (rfAvailable()) 571 | { 572 | r = rfRead(); 573 | } 574 | 575 | // otherwise, just take data from the keyboard 576 | byte k = SRXEGetKey(); 577 | if(k){ 578 | if(k == CONST_KEY_EXIT){ 579 | SRXEPowerDown(); 580 | SRXEPowerUp(); 581 | global.mode = CONST_MODE_CONSOLE; 582 | }else if(k == CONST_KEY_CLEAR){ 583 | clearScreen(); 584 | k = NULL; // prevents subprograms from operating on this input 585 | } 586 | } 587 | 588 | // figure out our mode 589 | switch(global.mode) 590 | { 591 | case CONST_MODE_HEX: 592 | mode_hex_loop(k); 593 | break; 594 | case CONST_MODE_RSSI: 595 | mode_rssi_loop(); 596 | break; 597 | case CONST_MODE_CONSOLE: 598 | default: 599 | mode_console_loop(r,k); 600 | } 601 | //redraw(); 602 | } 603 | -------------------------------------------------------------------------------- /sketch/RadioFunctions.h: -------------------------------------------------------------------------------- 1 | /* RadioFunctions.h 2 | A handful of sending and receiving functions for the 3 | ATmega128RFA1. 4 | by: Jim Lindblom 5 | SparkFun Electronics 6 | date: July 8, 2013 7 | license: Beerware. Use, distribut, and modify this code freely 8 | however you please. If you find it useful, you can buy me a beer 9 | some day. 10 | 11 | Functions in here: 12 | rfBegin(uint8_t channel) - Initializes the radio on a channel 13 | between 11 and 26. 14 | rfWrite(uint8_t b) - Sends a byte over the radio. 15 | rfPrint(String toPrint) - Sends a string over the radio. 16 | int rfAvailable() - Returns number of characters currently 17 | in receive buffer, ready to be read. 18 | char rfRead() - Reads a character out of the buffer. 19 | 20 | Interrupt Sub-Routines (ISRs) in here: 21 | TRX24_TX_END_vect - End of radio transfer. 22 | TRX24_RX_START_vect - Beginning of radio receive. 23 | TRX24_RX_END_vect - End of radio receive. Characters are 24 | collected into a buffer here. 25 | */ 26 | 27 | #include // Required for digitalWrites, etc. 28 | 29 | // Board pin definitions. 30 | const int RX_LED = 34; // B6 - RF RX LED 31 | const int TX_LED = 35; // B7 - RF TX LED 32 | uint8_t rssiRaw; // Global variable shared between RX ISRs 33 | 34 | // A buffer to maintain data being received by radio. 35 | const int RF_BUFFER_SIZE = 127; 36 | struct ringBuffer 37 | { 38 | unsigned char buffer[RF_BUFFER_SIZE]; 39 | volatile unsigned int head; 40 | volatile unsigned int tail; 41 | } radioRXBuffer; 42 | 43 | 44 | // Initialize the RFA1's low-power 2.4GHz transciever. 45 | // Sets up the state machine, and gets the radio into 46 | // the RX_ON state. Interrupts are enabled for RX 47 | // begin and end, as well as TX end. 48 | uint8_t rfBegin(uint8_t channel) 49 | { 50 | for (int i=0; i<128; i++) 51 | { 52 | radioRXBuffer.buffer[i] = 0; 53 | } 54 | radioRXBuffer.tail = 0; 55 | radioRXBuffer.head = 0; 56 | 57 | // Setup RX/TX LEDs: These are pins B6/34 (RX) and B7/35 (TX). 58 | pinMode(RX_LED, OUTPUT); 59 | digitalWrite(RX_LED, LOW); 60 | pinMode(TX_LED, OUTPUT); 61 | digitalWrite(TX_LED, LOW); 62 | 63 | // Transceiver Pin Register -- TRXPR. 64 | // This register can be used to reset the transceiver, without 65 | // resetting the MCU. 66 | TRXPR |= (1< 26)) channel = 11; 98 | PHY_CC_CCA = (PHY_CC_CCA & 0xE0) | channel; // Set the channel to 11 99 | 100 | // Finally, we'll enter into the RX_ON state. Now waiting for radio RX's, unless 101 | // we go into a transmitting state. 102 | TRX_STATE = (TRX_STATE & 0xE0) | RX_ON; // Default to receiver 103 | 104 | rssiRaw=0; 105 | return 1; 106 | } 107 | 108 | // This function sends a string of characters out of the radio. 109 | // Given a string, it'll format a frame, and send it out. 110 | void rfPrint(String toPrint) 111 | { 112 | uint8_t frame[127]; // We'll need to turn the string into an arry 113 | int length = toPrint.length(); // Get the length of the string 114 | for (int i=0; i 2 | #include "RadioFunctions.h" 3 | 4 | char messages[6][24]; 5 | char command[24] = "> "; 6 | char netbuff[24] = ""; 7 | unsigned int curs = 2; 8 | int ncurs = 0; 9 | int row=0; 10 | 11 | void setup() { 12 | // put your setup code here, to run once: 13 | 14 | SRXEInit(0xe7, 0xd6, 0xa2); // initialize display 15 | SRXEWriteString(0,120,command, FONT_LARGE, 3, 0); // draw large black text at x=0,y=120, fg=3, bg=0 16 | 17 | strcpy(messages[0], ""); 18 | strcpy(messages[1], ""); 19 | strcpy(messages[2], ""); 20 | strcpy(messages[3], ""); 21 | strcpy(messages[4], ""); 22 | strcpy(messages[5], ""); 23 | 24 | rfBegin(11); 25 | 26 | } 27 | 28 | void redraw() 29 | { 30 | SRXEWriteString(0,0 ,messages[(0+row)%6], FONT_LARGE, 3, 0); 31 | SRXEWriteString(0,20 ,messages[(1+row)%6], FONT_LARGE, 3, 0); 32 | SRXEWriteString(0,40 ,messages[(2+row)%6], FONT_LARGE, 3, 0); 33 | SRXEWriteString(0,60 ,messages[(3+row)%6], FONT_LARGE, 3, 0); 34 | SRXEWriteString(0,80 ,messages[(4+row)%6], FONT_LARGE, 3, 0); 35 | SRXEWriteString(0,100,messages[(5+row)%6], FONT_LARGE, 3, 0); 36 | 37 | SRXEWriteString(0,120,command, FONT_LARGE, 3, 0); 38 | } 39 | 40 | void submit(char* submission) 41 | { 42 | strcpy(messages[row]," "); 43 | strcpy(messages[row],submission); 44 | row = (row+1)%6; 45 | 46 | redraw(); 47 | } 48 | 49 | void loop() { 50 | 51 | // if we hear something on the radio, build up the net buffer 52 | if (rfAvailable()) 53 | { 54 | byte n = rfRead(); 55 | if(n) 56 | { 57 | if(n==3) 58 | { 59 | submit(netbuff); 60 | strcpy(netbuff, " "); 61 | ncurs = 0; 62 | } 63 | else 64 | { 65 | netbuff[ncurs]=n; 66 | ncurs = (ncurs+1)%24; 67 | } 68 | } 69 | } 70 | 71 | // otherwise, just take data from the keyboard 72 | byte k = SRXEGetKey(); 73 | if(k) 74 | { 75 | // submit on "return" (key right of 'Sym', box line box) 76 | if(k==0x0D) 77 | { 78 | if(curs>3) 79 | { 80 | submit(command+2); 81 | 82 | // transmit 83 | for(int i=2;i "); 91 | curs = 2; 92 | } 93 | else 94 | { 95 | //sprintf(command,"> %d",k); 96 | //sprintf(command,"> %02X",k); 97 | 98 | if(k >= 0x20 && k <= 0x7A){ 99 | //is it printable? 100 | command[curs]=k; 101 | //curs = (curs+1)%24; 102 | if(curs < 22) { 103 | curs++; 104 | } 105 | }else if(k == 0x08){ 106 | // backspace? 107 | if(curs > 2){ 108 | curs--; 109 | } 110 | command[curs] = 0x20; //space is your blank character 111 | } 112 | } 113 | } 114 | redraw(); 115 | } 116 | -------------------------------------------------------------------------------- /sketch/hexdump.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | char messages[6][24]; 4 | char command[24] = "> "; 5 | uint32_t addr = 0x00; 6 | int row = 0; 7 | 8 | void redraw() 9 | { 10 | SRXEWriteString(0,0 ,messages[(0+row)%6], FONT_LARGE, 3, 0); 11 | SRXEWriteString(0,20 ,messages[(1+row)%6], FONT_LARGE, 3, 0); 12 | SRXEWriteString(0,40 ,messages[(2+row)%6], FONT_LARGE, 3, 0); 13 | SRXEWriteString(0,60 ,messages[(3+row)%6], FONT_LARGE, 3, 0); 14 | SRXEWriteString(0,80 ,messages[(4+row)%6], FONT_LARGE, 3, 0); 15 | SRXEWriteString(0,100,messages[(5+row)%6], FONT_LARGE, 3, 0); 16 | SRXEWriteString(0,120,command, FONT_LARGE, 3, 0); 17 | } 18 | 19 | void readLine(uint32_t addr) 20 | { 21 | //uint8_t foo[5]; 22 | byte foo[4]; 23 | //memset(foo,0x00,5); 24 | //char foo; 25 | snprintf(command, 24, "> 0x%x", addr); 26 | for(int i = 0; i < 5; i++){ strcpy(messages[i],messages[i+1]); } 27 | for(int j = 0; j < 4; j++){ foo[j] = EEPROM.read(addr+j); } 28 | //foo = EEPROM.read(addr); 29 | snprintf(messages[5], 24, "%04x %02x%02x%02x%02x %c%c%c%c", addr, foo[0],foo[1],foo[2],foo[3], foo[0],foo[1],foo[2],foo[3]); 30 | redraw(); 31 | } 32 | 33 | void setup() { 34 | // put your setup code here, to run once: 35 | SRXEInit(0xe7, 0xd6, 0xa2); // initialize display 36 | SRXEWriteString(0,120,command, FONT_LARGE, 3, 0); // draw large black text at x=0,y=120, fg=3, bg=0 37 | for(int i = 0; i < 4*8; i++) 38 | { 39 | /*EEPROM.write(n*i+0,0xde); 40 | EEPROM.write(n*i+1,0xad); 41 | EEPROM.write(n*i+2,0xbe); 42 | EEPROM.write(n*i+3,0xef);*/ 43 | EEPROM.write(i,'A'); 44 | //delay(500); 45 | } 46 | while(addr < (6*4)) 47 | { 48 | readLine(addr); 49 | addr += 4; 50 | } 51 | } 52 | 53 | void loop() { 54 | // put your main code here, to run repeatedly: 55 | byte k = SRXEGetKey(); 56 | if(k) 57 | { 58 | readLine(addr); 59 | if(addr <= (4*1024)) 60 | { 61 | addr += 4; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /sketch/multi-chat.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include "RadioFunctions.h" 3 | #include 4 | 5 | char messages[6][24]; 6 | char command[32] = "> \x00R05e\x00"; 7 | char netbuff[24] = ""; 8 | unsigned int curs = 2; 9 | int ncurs = 0; 10 | int row=0; 11 | uint8_t canaryOffset = 27; 12 | 13 | // Operation mode constants 14 | #define CONST_MODE_CONSOLE 0 15 | #define CONST_MODE_HEX 1 16 | #define CONST_MODE_RSSI 2 17 | #define CONST_MODE_CHAT 3 18 | 19 | // Special keyboard constants 20 | #define CONST_KEY_CLEAR 0xF8 21 | #define CONST_KEY_EXIT 0xF9 22 | 23 | // EEPROM constants 24 | #define CONST_MEM_NAME 0x00000000 25 | 26 | struct global_t{ 27 | int mode = CONST_MODE_CONSOLE; 28 | char command[26] = "> "; 29 | char canary[5] = "R05e"; 30 | uint8_t name[256]; 31 | uint16_t hexdumpaddr; 32 | uint32_t rfChannel; 33 | uint8_t rows; // screen rows 34 | uint8_t columns; // screen columns 35 | } global; 36 | 37 | void reset(){ 38 | //EEPROM.write(CONST_MEM_NAME,0xFF); 39 | setName(""); 40 | readName(); 41 | } 42 | 43 | void setup() { 44 | // put your setup code here, to run once: 45 | SRXEInit(0xe7, 0xd6, 0xa2); // initialize display 46 | SRXEWriteString(0,120,global.command, FONT_LARGE, 3, 0); // draw large black text at x=0,y=120, fg=3, bg=0 47 | global.rows = 6; 48 | 49 | for(int i = 0; i < global.rows; i++){ 50 | strcpy(messages[i], ""); 51 | } 52 | resetInputBuffer(); 53 | global.mode = CONST_MODE_CONSOLE; 54 | global.rfChannel = 11; 55 | 56 | rfBegin(global.rfChannel); 57 | 58 | // Device is ready to go; check if this was a reboot or new use 59 | strcpy((char*)global.name, "uninitialized"); 60 | //setName("Bob"); // uncomment this for testing 61 | //reset(); 62 | readName(); 63 | if(global.name[0]==NULL){ 64 | // device is unininitialized 65 | submit("Hello!"); 66 | submit("What is your name?"); 67 | // TODO: fall into limited mode waiting for username and write to EEPROM 68 | } 69 | } 70 | 71 | void clearScreen(){ 72 | for(int i = 0; i < global.rows; i++){ submit(" "); } 73 | row = 0; 74 | } 75 | 76 | void readName() 77 | { 78 | for(int i = 0; i < 256; i++) 79 | { 80 | char nameByte = EEPROM.read(CONST_MEM_NAME+i); 81 | if(nameByte == 0xFF || nameByte == 0x00){ 82 | global.name[i] = 0x00; 83 | break; 84 | } 85 | global.name[i] = nameByte; 86 | } 87 | } 88 | 89 | void setName(char *name) 90 | { 91 | for(int i = 0; i < 256; i++) 92 | { 93 | if(name[i] == 0x20) 94 | { 95 | name[i] = 0x00; // no spaces 96 | } 97 | 98 | EEPROM.write(CONST_MEM_NAME+i,name[i]); 99 | if(name[i] == 0x00) 100 | { 101 | break; 102 | } 103 | } 104 | } 105 | 106 | void resetInputBuffer() 107 | { 108 | memcpy(global.command, "> ",26); 109 | curs = 2; 110 | } 111 | 112 | void redraw() 113 | { 114 | SRXEWriteString(0,0 ,messages[(0+row)%global.rows], FONT_LARGE, 3, 0); 115 | SRXEWriteString(0,20 ,messages[(1+row)%global.rows], FONT_LARGE, 3, 0); 116 | SRXEWriteString(0,40 ,messages[(2+row)%global.rows], FONT_LARGE, 3, 0); 117 | SRXEWriteString(0,60 ,messages[(3+row)%global.rows], FONT_LARGE, 3, 0); 118 | SRXEWriteString(0,80 ,messages[(4+row)%global.rows], FONT_LARGE, 3, 0); 119 | SRXEWriteString(0,100,messages[(5+row)%global.rows], FONT_LARGE, 3, 0); 120 | SRXEWriteString(0,120,global.command, FONT_LARGE, 3, 0); 121 | } 122 | 123 | void handleInput(char* cmd) 124 | { 125 | if(!memcmp(cmd,"set",3)) 126 | { 127 | char* item = strtok(cmd," "); 128 | if(item){ 129 | item = strtok(NULL," "); 130 | if(item){ 131 | if(!memcmp(item,"name",4)){ 132 | item = strtok(NULL," "); 133 | setName(item); 134 | readName(); 135 | }else{ 136 | submit("Item not recognized"); 137 | } 138 | }else{ 139 | submit("Malformed"); 140 | } 141 | } 142 | }else if(!memcmp(cmd,"read",4)){ 143 | char* item = strtok(cmd," "); 144 | if(item){ 145 | item = strtok(NULL, " "); 146 | if(item){ 147 | if(!memcmp(item,"name",4)){ 148 | submit((char*)global.name); 149 | }else{ 150 | submit("Item not recognized"); 151 | } 152 | }else{ 153 | submit("Malformed"); 154 | } 155 | } 156 | }else if(!memcmp(cmd,"hex",3)){ 157 | global.mode = CONST_MODE_HEX; 158 | global.hexdumpaddr = 0; 159 | // fill the first 6 lines of the screen 160 | while(global.hexdumpaddr < (6*4)) 161 | { 162 | readHexLine(global.hexdumpaddr); 163 | global.hexdumpaddr += 4; 164 | } 165 | }else if(!memcmp(cmd,"rssi",4)){ 166 | global.mode = CONST_MODE_RSSI; 167 | }else if(!memcmp(cmd,"chat",4)){ 168 | global.mode = CONST_MODE_CHAT; 169 | global.rfChannel = 11; 170 | rfBegin(global.rfChannel); 171 | }else if(!memcmp(cmd,"help",4)){ 172 | submit("there is no help"); 173 | }else{ 174 | submit(cmd); 175 | } 176 | } 177 | 178 | // submit(char*) 179 | // Prints the designated string to the screen buffer and forces a redraw 180 | void submit(char* submission) 181 | { 182 | strcpy(messages[row]," "); 183 | strncpy(messages[row],submission, 24); 184 | row = (row+1)%global.rows; 185 | //checkCanary(); 186 | resetInputBuffer(); 187 | redraw(); 188 | } 189 | 190 | void checkCanary() 191 | { 192 | //if(memcmp(command+canaryOffset,"R05e",4) != 0) { 193 | if(memcmp(global.canary,"R05e",4) != 0) { 194 | for(int i = 0; i < 6; i++){ strcpy(messages[i],"OMGH@XXE!"); } 195 | //redraw(); 196 | } 197 | } 198 | 199 | // readHexLine(uint32_t) 200 | // Read 4 bytes starting from the specified address and print it to the string formatted as: 201 | //
202 | void readHexLine(uint32_t addr) 203 | { 204 | byte foo[4]; 205 | char bar[26]; 206 | for(int j = 0; j < 4; j++){ foo[j] = EEPROM.read(addr+j); } 207 | snprintf(bar, 24, "%04x %02x%02x%02x%02x %c%c%c%c", addr, foo[0],foo[1],foo[2],foo[3], foo[0],foo[1],foo[2],foo[3]); 208 | bar[24] = 0x00; 209 | submit(bar); 210 | } 211 | 212 | void updateInputBuffer(byte k){ 213 | if(k >= 0x20 && k <= 0x7A){ 214 | //is it printable? 215 | global.command[curs]=k; 216 | //curs = (curs+1)%24; 217 | if(curs < 31){ //22) { 218 | curs++; 219 | } 220 | }else if(k == 0x08){ 221 | // backspace? 222 | if(curs > 2){ 223 | curs--; 224 | } 225 | global.command[curs] = 0x20; //space is your blank character 226 | } 227 | } 228 | 229 | // mode_hex_loop(byte) 230 | // This is the loop function for when the device is in hex-dump mode. 231 | // TODO: 232 | // - Enable reading backwards 233 | void mode_hex_loop(byte k){ 234 | if(k){ 235 | readHexLine(global.hexdumpaddr); 236 | if(global.hexdumpaddr <= (4*1024)) 237 | { 238 | global.hexdumpaddr += 4; 239 | } 240 | } 241 | } 242 | 243 | // mode_console_loop(byte) 244 | // This is the loop function for when the device is in console (default) mode 245 | void mode_console_loop(byte k){ 246 | if(k){ 247 | // submit on "return" (key right of 'Sym', box line box) 248 | if(k==0x0D) 249 | { 250 | if(curs>3) 251 | { 252 | handleInput(global.command+2); 253 | resetInputBuffer(); 254 | } 255 | }else{ 256 | //update input buffer 257 | updateInputBuffer(k); 258 | } 259 | } 260 | } 261 | 262 | // mode_chat_loop(byte,byte) 263 | // First byte is input from the radio, second byte is from the keyboard. Update the screen accordingly. 264 | void mode_chat_loop(byte r,byte k){ 265 | if(r){ 266 | if(r==3) 267 | { 268 | submit(netbuff); 269 | strcpy(netbuff, " "); 270 | ncurs = 0; 271 | } 272 | else 273 | { 274 | netbuff[ncurs]=r; 275 | ncurs = (ncurs+1)%24; 276 | } 277 | } 278 | 279 | if(k) 280 | { 281 | // submit on "return" (key right of 'Sym', box line box) 282 | if(k==0x0D) 283 | { 284 | if(curs>2) 285 | { 286 | // transmit 287 | for(int i=2;irfRead()){} // burn through the reads 322 | } 323 | snprintf(buf,24,"Ch %d: %d ",i,rssiRaw); 324 | 325 | global.rfChannel++; 326 | i = global.rfChannel; 327 | 328 | rfBegin(i); 329 | delay(100); 330 | 331 | y=(i-11)%8*17; 332 | if(i<19){ x = 0;} 333 | else { x = 201; } 334 | 335 | if(rfAvailable()) 336 | { 337 | while(0>rfRead()){} // burn through the reads 338 | } 339 | snprintf(buf2,12,"Ch %d: %d",i,rssiRaw); 340 | strncat(buf,buf2,24); 341 | submit(buf); 342 | 343 | global.rfChannel++; 344 | if(global.rfChannel > 26){ 345 | global.rfChannel = 11; 346 | } 347 | } 348 | 349 | void loop() { 350 | // if we hear something on the radio, build up the net buffer 351 | byte n = NULL; 352 | if (rfAvailable()) 353 | { 354 | n = rfRead(); 355 | } 356 | 357 | // otherwise, just take data from the keyboard 358 | byte k = SRXEGetKey(); 359 | if(k){ 360 | if(k == CONST_KEY_EXIT){ 361 | global.mode = CONST_MODE_CONSOLE; 362 | }else if(k == CONST_KEY_CLEAR){ 363 | clearScreen(); 364 | k = NULL; // prevents subprograms from operating on this input 365 | } 366 | } 367 | 368 | // figure out our mode 369 | switch(global.mode) 370 | { 371 | case CONST_MODE_HEX: 372 | mode_hex_loop(k); 373 | break; 374 | case CONST_MODE_RSSI: 375 | mode_rssi_loop(); 376 | break; 377 | case CONST_MODE_CHAT: 378 | mode_chat_loop(n,k); 379 | break; 380 | case CONST_MODE_CONSOLE: 381 | default: 382 | mode_console_loop(k); 383 | } 384 | redraw(); 385 | } 386 | -------------------------------------------------------------------------------- /sketch/multi-mode.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include "RadioFunctions.h" 3 | #include 4 | 5 | char messages[6][24]; 6 | char command[32] = "> \x00R05e\x00"; 7 | char netbuff[24] = ""; 8 | unsigned int curs = 2; 9 | int ncurs = 0; 10 | int row=0; 11 | uint8_t canaryOffset = 27; 12 | 13 | // Operation mode constants 14 | #define CONST_MODE_CHAT 0 15 | #define CONST_MODE_HEX 1 16 | #define CONST_MODE_RSSI 2 17 | 18 | // Special keyboard constants 19 | #define CONST_KEY_CLEAR 0xF8 20 | #define CONST_KEY_EXIT 0xF9 21 | 22 | // EEPROM constants 23 | #define CONST_MEM_NAME 0x00000000 24 | 25 | struct global_t{ 26 | int mode = CONST_MODE_CHAT; 27 | char command[26] = "> "; 28 | char canary[5] = "R05e"; 29 | uint8_t name[256]; 30 | uint16_t hexdumpaddr; 31 | uint32_t rfChannel; 32 | } global; 33 | 34 | void reset(){ 35 | //EEPROM.write(CONST_MEM_NAME,0xFF); 36 | setName(""); 37 | readName(); 38 | } 39 | 40 | void setup() { 41 | // put your setup code here, to run once: 42 | SRXEInit(0xe7, 0xd6, 0xa2); // initialize display 43 | SRXEWriteString(0,120,global.command, FONT_LARGE, 3, 0); // draw large black text at x=0,y=120, fg=3, bg=0 44 | strcpy(messages[0], ""); 45 | strcpy(messages[1], ""); 46 | strcpy(messages[2], ""); 47 | strcpy(messages[3], ""); 48 | strcpy(messages[4], ""); 49 | strcpy(messages[5], ""); 50 | resetInputBuffer(); 51 | global.mode = CONST_MODE_CHAT; 52 | global.rfChannel = 11; 53 | rfBegin(global.rfChannel); 54 | 55 | // Device is ready to go; check if this was a reboot or new use 56 | strcpy((char*)global.name, "uninitialized"); 57 | //setName("Bob"); // uncomment this for testing 58 | //reset(); 59 | readName(); 60 | if(global.name[0]==NULL){ 61 | // device is unininitialized 62 | submit("Hello!"); 63 | submit("What is your name?"); 64 | // TODO: fall into limited mode waiting for username and write to EEPROM 65 | } 66 | } 67 | 68 | void clearScreen(){ 69 | for(int i = 0; i < 6; i++){ submit(" "); } 70 | row = 0; 71 | } 72 | 73 | void readName() 74 | { 75 | for(int i = 0; i < 256; i++) 76 | { 77 | char nameByte = EEPROM.read(CONST_MEM_NAME+i); 78 | if(nameByte == 0xFF || nameByte == 0x00){ 79 | global.name[i] = 0x00; 80 | break; 81 | } 82 | global.name[i] = nameByte; 83 | } 84 | } 85 | 86 | void setName(char *name) 87 | { 88 | for(int i = 0; i < 256; i++) 89 | { 90 | if(name[i] == 0x20) 91 | { 92 | name[i] = 0x00; // no spaces 93 | } 94 | 95 | EEPROM.write(CONST_MEM_NAME+i,name[i]); 96 | if(name[i] == 0x00) 97 | { 98 | break; 99 | } 100 | } 101 | } 102 | 103 | void resetInputBuffer() 104 | { 105 | /*memcpy(command,">",1); 106 | memcpy(command+1," ",30); 107 | memcpy(command+27,"R05e",4); 108 | memcpy(command+31,0x00,1); 109 | memcpy(command+25,0x00,1);*/ 110 | 111 | //memcpy(command, "> \x00R05e\x00",26); 112 | memcpy(global.command, "> ",26); 113 | } 114 | 115 | void redraw() 116 | { 117 | SRXEWriteString(0,0 ,messages[(0+row)%6], FONT_LARGE, 3, 0); 118 | SRXEWriteString(0,20 ,messages[(1+row)%6], FONT_LARGE, 3, 0); 119 | SRXEWriteString(0,40 ,messages[(2+row)%6], FONT_LARGE, 3, 0); 120 | SRXEWriteString(0,60 ,messages[(3+row)%6], FONT_LARGE, 3, 0); 121 | SRXEWriteString(0,80 ,messages[(4+row)%6], FONT_LARGE, 3, 0); 122 | SRXEWriteString(0,100,messages[(5+row)%6], FONT_LARGE, 3, 0); 123 | 124 | SRXEWriteString(0,120,global.command, FONT_LARGE, 3, 0); 125 | } 126 | 127 | void handleInput(char* cmd) 128 | { 129 | if(!memcmp(cmd,"set",3)) 130 | { 131 | char* item = strtok(cmd," "); 132 | if(item){ 133 | item = strtok(NULL," "); 134 | if(item){ 135 | if(!memcmp(item,"name",4)){ 136 | item = strtok(NULL," "); 137 | setName(item); 138 | readName(); 139 | }else{ 140 | submit("Item not recognized"); 141 | } 142 | }else{ 143 | submit("Malformed"); 144 | } 145 | } 146 | }else if(!memcmp(cmd,"read",4)){ 147 | char* item = strtok(cmd," "); 148 | if(item){ 149 | item = strtok(NULL, " "); 150 | if(item){ 151 | if(!memcmp(item,"name",4)){ 152 | submit((char*)global.name); 153 | }else{ 154 | submit("Item not recognized"); 155 | } 156 | }else{ 157 | submit("Malformed"); 158 | } 159 | } 160 | }else if(!memcmp(cmd,"hex",3)){ 161 | global.mode = CONST_MODE_HEX; 162 | global.hexdumpaddr = 0; 163 | // fill the first 6 lines of the screen 164 | while(global.hexdumpaddr < (6*4)) 165 | { 166 | readHexLine(global.hexdumpaddr); 167 | global.hexdumpaddr += 4; 168 | } 169 | }else if(!memcmp(cmd,"rssi",4)){ 170 | global.mode = CONST_MODE_RSSI; 171 | }else if(!memcmp(cmd,"help",4)){ 172 | submit("there is no help"); 173 | }else{ 174 | submit(cmd); 175 | } 176 | } 177 | 178 | // submit(char*) 179 | // Prints the designated string to the screen buffer and forces a readraw 180 | void submit(char* submission) 181 | { 182 | strcpy(messages[row]," "); 183 | strncpy(messages[row],submission, 24); 184 | row = (row+1)%6; 185 | //checkCanary(); 186 | resetInputBuffer(); 187 | redraw(); 188 | } 189 | 190 | void checkCanary() 191 | { 192 | //if(memcmp(command+canaryOffset,"R05e",4) != 0) { 193 | if(memcmp(global.canary,"R05e",4) != 0) { 194 | for(int i = 0; i < 6; i++){ strcpy(messages[i],"OMGH@XXE!"); } 195 | //redraw(); 196 | } 197 | } 198 | 199 | // readHexLine(uint32_t) 200 | // Read 4 bytes starting from the specified address and print it to the string formatted as: 201 | //
202 | void readHexLine(uint32_t addr) 203 | { 204 | byte foo[4]; 205 | char bar[26]; 206 | for(int j = 0; j < 4; j++){ foo[j] = EEPROM.read(addr+j); } 207 | snprintf(bar, 24, "%04x %02x%02x%02x%02x %c%c%c%c", addr, foo[0],foo[1],foo[2],foo[3], foo[0],foo[1],foo[2],foo[3]); 208 | bar[24] = 0x00; 209 | submit(bar); 210 | } 211 | 212 | // mode_hex_loop(byte) 213 | // This is the loop function for when the device is in hex-dump mode. 214 | // TODO: 215 | // - Enable reading backwards 216 | void mode_hex_loop(byte k){ 217 | if(k){ 218 | readHexLine(global.hexdumpaddr); 219 | if(global.hexdumpaddr <= (4*1024)) 220 | { 221 | global.hexdumpaddr += 4; 222 | } 223 | } 224 | } 225 | 226 | // mode_chat_loop(byte) 227 | // This is the loop function for when the device is in chat (default) mode 228 | void mode_chat_loop(byte k){ 229 | if(k) 230 | { 231 | // submit on "return" (key right of 'Sym', box line box) 232 | if(k==0x0D) 233 | { 234 | if(curs>3) 235 | { 236 | //submit(global.command+2); 237 | handleInput(global.command+2); 238 | 239 | // transmit 240 | for(int i=2;i ",26);//canaryOffset-1); 251 | curs = 2; 252 | } 253 | else 254 | { 255 | 256 | if(k >= 0x20 && k <= 0x7A){ 257 | //is it printable? 258 | global.command[curs]=k; 259 | //curs = (curs+1)%24; 260 | if(curs < 31){ //22) { 261 | curs++; 262 | } 263 | }else if(k == 0x08){ 264 | // backspace? 265 | if(curs > 2){ 266 | curs--; 267 | } 268 | global.command[curs] = 0x20; //space is your blank character 269 | } 270 | } 271 | } 272 | } 273 | 274 | // mode_rssi_loop() 275 | // This is a port of earlier RSSI code 276 | void mode_rssi_loop(){ 277 | int x; 278 | int y; 279 | char buf[24]; 280 | char buf2[12]; 281 | int i = global.rfChannel; 282 | 283 | rfBegin(i); 284 | delay(100); 285 | 286 | y=(i-11)%8*17; 287 | if(i<19){ x = 0;} 288 | else { x = 201; } 289 | 290 | if(rfAvailable()) 291 | { 292 | while(0>rfRead()){} // burn through the reads 293 | //snprintf(buf,24,"Ch %d : %d ",i,rssiRaw); 294 | //submit(buf); 295 | } 296 | //else 297 | //{ 298 | snprintf(buf,24,"Ch %d: %d ",i,rssiRaw); 299 | // submit(buf); 300 | //} 301 | 302 | global.rfChannel++; 303 | i = global.rfChannel; 304 | 305 | rfBegin(i); 306 | delay(100); 307 | 308 | y=(i-11)%8*17; 309 | if(i<19){ x = 0;} 310 | else { x = 201; } 311 | 312 | if(rfAvailable()) 313 | { 314 | while(0>rfRead()){} // burn through the reads 315 | } 316 | snprintf(buf2,12,"Ch %d: %d",i,rssiRaw); 317 | strncat(buf,buf2,24); 318 | submit(buf); 319 | 320 | global.rfChannel++; 321 | if(global.rfChannel > 26){ 322 | global.rfChannel = 11; 323 | } 324 | } 325 | 326 | void loop() { 327 | // if we hear something on the radio, build up the net buffer 328 | if (rfAvailable()) 329 | { 330 | byte n = rfRead(); 331 | if(n) 332 | { 333 | if(n==3) 334 | { 335 | submit(netbuff); 336 | strcpy(netbuff, " "); 337 | ncurs = 0; 338 | } 339 | else 340 | { 341 | netbuff[ncurs]=n; 342 | ncurs = (ncurs+1)%24; 343 | } 344 | } 345 | } 346 | 347 | // otherwise, just take data from the keyboard 348 | byte k = SRXEGetKey(); 349 | if(k){ 350 | if(k == CONST_KEY_EXIT){ 351 | global.mode = CONST_MODE_CHAT; 352 | }else if(k == CONST_KEY_CLEAR){ 353 | clearScreen(); 354 | k = NULL; // prevents subprograms from operating on this input 355 | } 356 | } 357 | 358 | // figure out our mode 359 | switch(global.mode) 360 | { 361 | case CONST_MODE_HEX: 362 | mode_hex_loop(k); 363 | break; 364 | case CONST_MODE_RSSI: 365 | mode_rssi_loop(); 366 | break; 367 | case CONST_MODE_CHAT: 368 | default: 369 | mode_chat_loop(k); 370 | } 371 | redraw(); 372 | } 373 | -------------------------------------------------------------------------------- /sketch/quest.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include "RadioFunctions.h" 3 | #include 4 | 5 | char messages[6][24]; 6 | char command[32] = "> \x00R05e\x00"; 7 | char netbuff[24] = ""; 8 | unsigned int curs = 2; 9 | int ncurs = 0; 10 | int row=0; 11 | uint8_t canaryOffset = 27; 12 | 13 | #define NAME_ADDR 0x00000000 14 | 15 | struct global_t{ 16 | char command[26] = "> "; 17 | char canary[5] = "R05e"; 18 | uint8_t name[256]; 19 | } global; 20 | 21 | void setup() { 22 | // put your setup code here, to run once: 23 | 24 | SRXEInit(0xe7, 0xd6, 0xa2); // initialize display 25 | SRXEWriteString(0,120,global.command, FONT_LARGE, 3, 0); // draw large black text at x=0,y=120, fg=3, bg=0 26 | strcpy((char*)global.name, "uninitialized"); 27 | 28 | //setName("Bob"); 29 | readName(); 30 | strcpy(messages[0], "Hi there..."); 31 | //strcpy(messages[1], ""); 32 | memcpy(messages[1], global.name, 24); 33 | strcpy(messages[2], ""); 34 | strcpy(messages[3], ""); 35 | strcpy(messages[4], ""); 36 | strcpy(messages[5], ""); 37 | resetInputBuffer(); 38 | rfBegin(11); 39 | } 40 | 41 | void readName() 42 | { 43 | //SRXEFlashRead(NAME_ADDR,global.name,256); 44 | for(int i = 0; i < 256; i++) 45 | { 46 | char nameByte = EEPROM.read(NAME_ADDR+i); 47 | if(nameByte == 0x00){ 48 | break; 49 | } 50 | global.name[i] = nameByte; 51 | } 52 | } 53 | 54 | void setName(char *name) 55 | { 56 | /*uint8_t foo[256]; 57 | memset(foo,0x00,256); 58 | strcpy((char*)foo,name); 59 | bool result = SRXEFlashWritePage(NAME_ADDR,foo); 60 | delay(100);*/ 61 | memset(global.name,0x00,256); 62 | for(int i = 0; i < 256; i++) 63 | { 64 | if(name[i] == 0x00) 65 | { 66 | break; 67 | } 68 | EEPROM.write(NAME_ADDR+i,name[i]); 69 | } 70 | //return(result); 71 | } 72 | 73 | void resetInputBuffer() 74 | { 75 | /*memcpy(command,">",1); 76 | memcpy(command+1," ",30); 77 | memcpy(command+27,"R05e",4); 78 | memcpy(command+31,0x00,1); 79 | memcpy(command+25,0x00,1);*/ 80 | 81 | //memcpy(command, "> \x00R05e\x00",26); 82 | memcpy(global.command, "> ",26); 83 | } 84 | 85 | void redraw() 86 | { 87 | SRXEWriteString(0,0 ,messages[(0+row)%6], FONT_LARGE, 3, 0); 88 | SRXEWriteString(0,20 ,messages[(1+row)%6], FONT_LARGE, 3, 0); 89 | SRXEWriteString(0,40 ,messages[(2+row)%6], FONT_LARGE, 3, 0); 90 | SRXEWriteString(0,60 ,messages[(3+row)%6], FONT_LARGE, 3, 0); 91 | SRXEWriteString(0,80 ,messages[(4+row)%6], FONT_LARGE, 3, 0); 92 | SRXEWriteString(0,100,messages[(5+row)%6], FONT_LARGE, 3, 0); 93 | 94 | SRXEWriteString(0,120,global.command, FONT_LARGE, 3, 0); 95 | } 96 | 97 | void submit(char* submission) 98 | { 99 | strcpy(messages[row]," "); 100 | strncpy(messages[row],submission, 26); 101 | row = (row+1)%6; 102 | checkCanary(); 103 | setName(submission); 104 | readName(); 105 | strncpy(messages[1],(char*)global.name, 26); 106 | resetInputBuffer(); 107 | redraw(); 108 | } 109 | 110 | void checkCanary() 111 | { 112 | //if(memcmp(command+canaryOffset,"R05e",4) != 0) { 113 | if(memcmp(global.canary,"R05e",4) != 0) { 114 | for(int i = 0; i < 6; i++){ strcpy(messages[i],"OMGH@XXE!"); } 115 | //redraw(); 116 | } 117 | } 118 | 119 | void loop() { 120 | 121 | // if we hear something on the radio, build up the net buffer 122 | if (rfAvailable()) 123 | { 124 | byte n = rfRead(); 125 | if(n) 126 | { 127 | if(n==3) 128 | { 129 | submit(netbuff); 130 | strcpy(netbuff, " "); 131 | ncurs = 0; 132 | } 133 | else 134 | { 135 | netbuff[ncurs]=n; 136 | ncurs = (ncurs+1)%24; 137 | } 138 | } 139 | } 140 | 141 | // otherwise, just take data from the keyboard 142 | byte k = SRXEGetKey(); 143 | if(k) 144 | { 145 | // submit on "return" (key right of 'Sym', box line box) 146 | if(k==0x0D) 147 | { 148 | if(curs>3) 149 | { 150 | submit(global.command+2); 151 | 152 | // transmit 153 | for(int i=2;i ",26);//canaryOffset-1); 164 | //memcpy(command, "> \x00R05e\x00",26);//canaryOffset-1); 165 | curs = 2; 166 | /*if(memcmp(command+60,"R05e",4) == 0) { 167 | memcpy(command, "> ",26);//canaryOffset-1); 168 | curs = 2; 169 | }else{ 170 | //strcpy(command, "OMGH@XXE!"); 171 | submit("OMGH@XXE!"); 172 | }*/ 173 | } 174 | else 175 | { 176 | //sprintf(command,"> %d",k); 177 | //sprintf(command,"> %02X",k); 178 | 179 | if(k >= 0x20 && k <= 0x7A){ 180 | //is it printable? 181 | global.command[curs]=k; 182 | //curs = (curs+1)%24; 183 | if(curs < 31){ //22) { 184 | curs++; 185 | } 186 | }else if(k == 0x08){ 187 | // backspace? 188 | if(curs > 2){ 189 | curs--; 190 | } 191 | global.command[curs] = 0x20; //space is your blank character 192 | } 193 | } 194 | } 195 | redraw(); 196 | } 197 | -------------------------------------------------------------------------------- /sketch/rssi.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include "RadioFunctions.h" 3 | 4 | char messages[6][24]; 5 | char command[24] = "> "; 6 | char netbuff[24] = ""; 7 | int curs = 2; 8 | int ncurs = 0; 9 | int row=0; 10 | 11 | void setup() { 12 | // put your setup code here, to run once: 13 | 14 | SRXEInit(0xe7, 0xd6, 0xa2); // initialize display 15 | //SRXEWriteString(0,120,command, FONT_LARGE, 3, 0); // draw large black text at x=0,y=120, fg=3, bg=0 16 | 17 | strcpy(messages[0], ""); 18 | strcpy(messages[1], ""); 19 | strcpy(messages[2], ""); 20 | strcpy(messages[3], ""); 21 | strcpy(messages[4], ""); 22 | strcpy(messages[5], ""); 23 | 24 | //rfBegin(24); 25 | 26 | } 27 | 28 | void redraw() 29 | { 30 | SRXEWriteString(0,0 ,messages[(0+row)%6], FONT_LARGE, 3, 0); 31 | SRXEWriteString(0,20 ,messages[(1+row)%6], FONT_LARGE, 3, 0); 32 | SRXEWriteString(0,40 ,messages[(2+row)%6], FONT_LARGE, 3, 0); 33 | SRXEWriteString(0,60 ,messages[(3+row)%6], FONT_LARGE, 3, 0); 34 | SRXEWriteString(0,80 ,messages[(4+row)%6], FONT_LARGE, 3, 0); 35 | SRXEWriteString(0,100,messages[(5+row)%6], FONT_LARGE, 3, 0); 36 | 37 | SRXEWriteString(0,120,command, FONT_LARGE, 3, 0); 38 | } 39 | 40 | void submit(char* submission) 41 | { 42 | strcpy(messages[row]," "); 43 | strcpy(messages[row],submission); 44 | row = (row+1)%6; 45 | 46 | redraw(); 47 | } 48 | 49 | void loop() { 50 | 51 | int x; 52 | int y; 53 | 54 | for(int i=11;i<=26;++i) 55 | { 56 | rfBegin(i); 57 | delay(100); 58 | 59 | y=(i-11)%8*17; 60 | if(i<19){ x = 0;} 61 | else { x = 201; } 62 | 63 | if(rfAvailable()) 64 | { 65 | while(0>rfRead()){} // burn through the reads 66 | sprintf(command,"Ch %d : %d ",i,rssiRaw); 67 | SRXEWriteString(x,y ,command, FONT_LARGE, 3, 0); 68 | 69 | } 70 | else 71 | { 72 | sprintf(command,"Ch %d : %d ",i,rssiRaw); 73 | SRXEWriteString(x,y ,command, FONT_LARGE, 3, 0); 74 | } 75 | 76 | } 77 | 78 | 79 | } 80 | --------------------------------------------------------------------------------