├── .github └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── README.md ├── boards.txt ├── cores └── wasm32 │ ├── Arduino.h │ ├── HardwareSerial.cpp │ ├── HardwareSerial.h │ ├── Itoa.cpp │ ├── Itoa.h │ ├── Print.cpp │ ├── Print.h │ ├── Printable.h │ ├── Stream.cpp │ ├── Stream.h │ ├── WString.cpp │ ├── WString.h │ ├── Wasmino.cpp │ ├── Wasmino.h │ └── binary.h ├── package.py ├── package_index_template.json ├── platform.txt ├── programmers.txt └── requirements.txt /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | release: 5 | types: [ created ] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v2 13 | 14 | - name: Get Release Info 15 | id: get_release 16 | uses: bruceadams/get-release@v1.2.2 17 | env: 18 | GITHUB_TOKEN: ${{ github.token }} 19 | 20 | - name: Build Package 21 | run: | 22 | python3 package.py --package=package.zip --package-url https://github.com/wasmino/wasmino-core/releases/download/${{ steps.get_release.outputs.tag_name }}/package.zip 23 | 24 | - name: Upload Package ZIP 25 | uses: actions/upload-release-asset@v1.0.2 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | with: 29 | upload_url: ${{ steps.get_release.outputs.upload_url }} 30 | asset_path: package.zip 31 | asset_name: package.zip 32 | asset_content_type: application/zip 33 | 34 | - name: Upload Package Index 35 | uses: actions/upload-release-asset@v1.0.2 36 | env: 37 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 38 | with: 39 | upload_url: ${{ steps.get_release.outputs.upload_url }} 40 | asset_path: package_wasmino_index.json 41 | asset_name: package_wasmino_index.json 42 | asset_content_type: application/json 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.zip 2 | .vscode 3 | .venv 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2020 Yifan Gu 2 | 3 | This library is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU Lesser General Public 5 | License as published by the Free Software Foundation; either 6 | version 2.1 of the License, or (at your option) any later version. 7 | 8 | This library is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 | Lesser General Public License for more details. 12 | 13 | You should have received a copy of the GNU Lesser General Public 14 | License along with this library; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 16 | USA 17 | 18 | 19 | GNU LESSER GENERAL PUBLIC LICENSE 20 | Version 3, 29 June 2007 21 | 22 | Copyright (C) 2007 Free Software Foundation, Inc. 23 | Everyone is permitted to copy and distribute verbatim copies 24 | of this license document, but changing it is not allowed. 25 | 26 | 27 | This version of the GNU Lesser General Public License incorporates 28 | the terms and conditions of version 3 of the GNU General Public 29 | License, supplemented by the additional permissions listed below. 30 | 31 | 0. Additional Definitions. 32 | 33 | As used herein, "this License" refers to version 3 of the GNU Lesser 34 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 35 | General Public License. 36 | 37 | "The Library" refers to a covered work governed by this License, 38 | other than an Application or a Combined Work as defined below. 39 | 40 | An "Application" is any work that makes use of an interface provided 41 | by the Library, but which is not otherwise based on the Library. 42 | Defining a subclass of a class defined by the Library is deemed a mode 43 | of using an interface provided by the Library. 44 | 45 | A "Combined Work" is a work produced by combining or linking an 46 | Application with the Library. The particular version of the Library 47 | with which the Combined Work was made is also called the "Linked 48 | Version". 49 | 50 | The "Minimal Corresponding Source" for a Combined Work means the 51 | Corresponding Source for the Combined Work, excluding any source code 52 | for portions of the Combined Work that, considered in isolation, are 53 | based on the Application, and not on the Linked Version. 54 | 55 | The "Corresponding Application Code" for a Combined Work means the 56 | object code and/or source code for the Application, including any data 57 | and utility programs needed for reproducing the Combined Work from the 58 | Application, but excluding the System Libraries of the Combined Work. 59 | 60 | 1. Exception to Section 3 of the GNU GPL. 61 | 62 | You may convey a covered work under sections 3 and 4 of this License 63 | without being bound by section 3 of the GNU GPL. 64 | 65 | 2. Conveying Modified Versions. 66 | 67 | If you modify a copy of the Library, and, in your modifications, a 68 | facility refers to a function or data to be supplied by an Application 69 | that uses the facility (other than as an argument passed when the 70 | facility is invoked), then you may convey a copy of the modified 71 | version: 72 | 73 | a) under this License, provided that you make a good faith effort to 74 | ensure that, in the event an Application does not supply the 75 | function or data, the facility still operates, and performs 76 | whatever part of its purpose remains meaningful, or 77 | 78 | b) under the GNU GPL, with none of the additional permissions of 79 | this License applicable to that copy. 80 | 81 | 3. Object Code Incorporating Material from Library Header Files. 82 | 83 | The object code form of an Application may incorporate material from 84 | a header file that is part of the Library. You may convey such object 85 | code under terms of your choice, provided that, if the incorporated 86 | material is not limited to numerical parameters, data structure 87 | layouts and accessors, or small macros, inline functions and templates 88 | (ten or fewer lines in length), you do both of the following: 89 | 90 | a) Give prominent notice with each copy of the object code that the 91 | Library is used in it and that the Library and its use are 92 | covered by this License. 93 | 94 | b) Accompany the object code with a copy of the GNU GPL and this license 95 | document. 96 | 97 | 4. Combined Works. 98 | 99 | You may convey a Combined Work under terms of your choice that, 100 | taken together, effectively do not restrict modification of the 101 | portions of the Library contained in the Combined Work and reverse 102 | engineering for debugging such modifications, if you also do each of 103 | the following: 104 | 105 | a) Give prominent notice with each copy of the Combined Work that 106 | the Library is used in it and that the Library and its use are 107 | covered by this License. 108 | 109 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 110 | document. 111 | 112 | c) For a Combined Work that displays copyright notices during 113 | execution, include the copyright notice for the Library among 114 | these notices, as well as a reference directing the user to the 115 | copies of the GNU GPL and this license document. 116 | 117 | d) Do one of the following: 118 | 119 | 0) Convey the Minimal Corresponding Source under the terms of this 120 | License, and the Corresponding Application Code in a form 121 | suitable for, and under terms that permit, the user to 122 | recombine or relink the Application with a modified version of 123 | the Linked Version to produce a modified Combined Work, in the 124 | manner specified by section 6 of the GNU GPL for conveying 125 | Corresponding Source. 126 | 127 | 1) Use a suitable shared library mechanism for linking with the 128 | Library. A suitable mechanism is one that (a) uses at run time 129 | a copy of the Library already present on the user's computer 130 | system, and (b) will operate properly with a modified version 131 | of the Library that is interface-compatible with the Linked 132 | Version. 133 | 134 | e) Provide Installation Information, but only if you would otherwise 135 | be required to provide such information under section 6 of the 136 | GNU GPL, and only to the extent that such information is 137 | necessary to install and execute a modified version of the 138 | Combined Work produced by recombining or relinking the 139 | Application with a modified version of the Linked Version. (If 140 | you use option 4d0, the Installation Information must accompany 141 | the Minimal Corresponding Source and Corresponding Application 142 | Code. If you use option 4d1, you must provide the Installation 143 | Information in the manner specified by section 6 of the GNU GPL 144 | for conveying Corresponding Source.) 145 | 146 | 5. Combined Libraries. 147 | 148 | You may place library facilities that are a work based on the 149 | Library side by side in a single library together with other library 150 | facilities that are not Applications and are not covered by this 151 | License, and convey such a combined library under terms of your 152 | choice, if you do both of the following: 153 | 154 | a) Accompany the combined library with a copy of the same work based 155 | on the Library, uncombined with any other library facilities, 156 | conveyed under the terms of this License. 157 | 158 | b) Give prominent notice with the combined library that part of it 159 | is a work based on the Library, and explaining where to find the 160 | accompanying uncombined form of the same work. 161 | 162 | 6. Revised Versions of the GNU Lesser General Public License. 163 | 164 | The Free Software Foundation may publish revised and/or new versions 165 | of the GNU Lesser General Public License from time to time. Such new 166 | versions will be similar in spirit to the present version, but may 167 | differ in detail to address new problems or concerns. 168 | 169 | Each version is given a distinguishing version number. If the 170 | Library as you received it specifies that a certain numbered version 171 | of the GNU Lesser General Public License "or any later version" 172 | applies to it, you have the option of following the terms and 173 | conditions either of that published version or of any later version 174 | published by the Free Software Foundation. If the Library as you 175 | received it does not specify a version number of the GNU Lesser 176 | General Public License, you may choose any version of the GNU Lesser 177 | General Public License ever published by the Free Software Foundation. 178 | 179 | If the Library as you received it specifies that a proxy can decide 180 | whether future versions of the GNU Lesser General Public License shall 181 | apply, that proxy's public statement of acceptance of any version is 182 | permanent authorization for you to choose that version for the 183 | Library. 184 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Wasmino = WASM + Arduino (Running Arduino code in browser)](https://blog.yifangu.com/2020/12/30/wasmino-wasm-arduino-running-arduino-code-in-browser/) 2 | ------------------------------------------------------------------------------------------------------------------------------------------------------- 3 | 4 | ![](https://yifangucom.files.wordpress.com/2020/12/wasmino.gif?w=320) 5 | 6 | Wasmino Running the “Fade” example 7 | 8 | Wasmino is an Arduino core fully compatible with the Arduino IDE. It allows you to compile your Arduino sketch to WebAssembly and run it in a browser, all using the Arduino IDE. 9 | 10 | Showcase 11 | -------- 12 | 13 | This is the off-the-shelf “Fade” example in the Arduino IDE. 14 | 15 | ```C++ 16 | /* 17 | Fade 18 | 19 | This example shows how to fade an LED on pin 9 using the analogWrite() 20 | function. 21 | 22 | The analogWrite() function uses PWM, so if you want to change the pin you're 23 | using, be sure to use another PWM capable pin. On most Arduino, the PWM pins 24 | are identified with a "~" sign, like ~3, ~5, ~6, ~9, ~10 and ~11. 25 | 26 | This example code is in the public domain. 27 | 28 | http://www.arduino.cc/en/Tutorial/Fade 29 | */ 30 | 31 | int led = 9; // the PWM pin the LED is attached to 32 | int brightness = 0; // how bright the LED is 33 | int fadeAmount = 5; // how many points to fade the LED by 34 | 35 | // the setup routine runs once when you press reset: 36 | void setup() { 37 | // declare pin 9 to be an output: 38 | pinMode(led, OUTPUT); 39 | } 40 | 41 | // the loop routine runs over and over again forever: 42 | void loop() { 43 | // set the brightness of pin 9: 44 | analogWrite(led, brightness); 45 | 46 | // change the brightness for next time through the loop: 47 | brightness = brightness + fadeAmount; 48 | 49 | // reverse the direction of the fading at the ends of the fade: 50 | if (brightness <= 0 || brightness >= 255) { 51 | fadeAmount = -fadeAmount; 52 | } 53 | // wait for 30 milliseconds to see the dimming effect 54 | delay(30); 55 | } 56 | ``` 57 | 58 | 59 | You can see it compiled to WASM and running here: 60 | 61 | (**Click the “Run” button** and the LED should start to animate) 62 | 63 | [https://demo.wasmino.org/#src=gist%3A%2F%2F01734051e7ab5b82173ea947b882ad80&pins=%7B%229%22%3A%7B%22type%22%3A%22led%22%7D%7D](https://demo.wasmino.org/#src=gist%3A%2F%2F01734051e7ab5b82173ea947b882ad80&pins=%7B%229%22%3A%7B%22type%22%3A%22led%22%7D%7D) 64 | 65 | Setting it up 66 | ------------- 67 | 68 | Disclaimer: The toolchain is only tested on Windows (x86-64) and Linux (x86-64), and probably will work for MacOS. It 100% won’t work on 32bit systems since some dependencies (WASI and Binaryen) are 64bit only. 69 | 70 | You’ll need your Arduino IDE installed first. 71 | 72 | Go to File -> Preferences, and add [https://github.com/wasmino/wasmino-core/releases/download/v0.0.1/package\_wasmino\_index.json](https://github.com/wasmino/wasmino-core/releases/download/v0.0.1/package_wasmino_index.json) to “Additional Boards Manager URLs”. 73 | 74 | ![](https://yifangucom.files.wordpress.com/2020/12/image.png?w=969) 75 | 76 | Install “Wasmino Virtual Boards” in Tools -> Board -> Board Manager. Select Wasmino as as target board. 77 | 78 | Write some Arduino code, click upload, and an URL will be generated for you. (If you are uploading for the first time, it will ask you to login to your GitHub account. It uses GitHub Gist for saving the compiled WASM binary. The login times out in 60 seconds.) 79 | 80 | ![](https://yifangucom.files.wordpress.com/2020/12/image-1.png?w=969) 81 | 82 | Paste that URL into your browser and use the UI to add LEDs or toggle switches. The URL will automatically update as you make changes. You can then copy the resulting URL in the browser and share it with other people. 83 | 84 | Caveats 85 | ------- 86 | 87 | The Wasmino should be viewed as having an infinitely fast CPU, and operations other than delay and delayMicroseconds do not take any CPU time. Calling time functions micros and millis should reflect this. IO can only happen during sleep, therefore you cannot do 88 | 89 | ```C++ 90 | while (!digitalRead(2)) {} // this will hang the browser tab 91 | ``` 92 | 93 | and should do this instead 94 | ```C++ 95 | while (!digitalRead(2)) { 96 | delay(50); 97 | } 98 | ``` 99 | 100 | Having a infinitely fast CPU also means that interrupts will only happen during delay and delayMicroseconds. It is still good practice to use noInterrupts and interrupts to protect critical sections if you plan to use your code on real hardware. 101 | 102 | Other caveats exist such as the lack of BUILTIN_LED macro since Wasmino, being virtual, doesn’t have a built-in LED. 103 | 104 | What works and what doesn’t work 105 | -------------------------------- 106 | 107 | 108 | From: https://www.arduino.cc/reference/en/ 109 | 110 | y: working 111 | n: not working 112 | 113 | Digital I/O 114 | y digitalRead() 115 | y digitalWrite() 116 | y pinMode() 117 | Analog I/O 118 | y* analogRead() 119 | n analogReference() 120 | y analogWrite() 121 | Zero, Due & MKR Family 122 | n analogReadResolution() 123 | n analogWriteResolution() 124 | Advanced I/O 125 | n noTone() 126 | n pulseIn() 127 | n pulseInLong() 128 | n shiftIn() 129 | n shiftOut() 130 | n tone() 131 | Time 132 | y delay() 133 | y delayMicroseconds() 134 | y micros() 135 | y millis() 136 | Math 137 | y abs() 138 | y constrain() 139 | y map() 140 | y max() 141 | y min() 142 | y pow() 143 | y sq() 144 | y sqrt() 145 | Trigonometry 146 | y cos() 147 | y sin() 148 | y tan() 149 | Characters 150 | n isAlpha() 151 | n isAlphaNumeric() 152 | n isAscii() 153 | n isControl() 154 | n isDigit() 155 | n isGraph() 156 | n isHexadecimalDigit() 157 | n isLowerCase() 158 | n isPrintable() 159 | n isPunct() 160 | n isSpace() 161 | n isUpperCase() 162 | n isWhitespace() 163 | Random Numbers 164 | n random() 165 | n randomSeed() 166 | Bits and Bytes 167 | y bit() 168 | y bitClear() 169 | y bitRead() 170 | y bitSet() 171 | y bitWrite() 172 | y highByte() 173 | y lowByte() 174 | External Interrupts 175 | y attachInterrupt() 176 | y detachInterrupt() 177 | Interrupts 178 | y interrupts() 179 | y noInterrupts() 180 | Communication 181 | y* Serial 182 | y Stream 183 | USB 184 | n Keyboard 185 | n Mouse 186 | 187 | * Not exposed in the demo web app. 188 | * Not exposed in the demo web app. 189 | 190 | 191 | The Wasmino Arduino core is available at [https://github.com/wasmino/wasmino-core](https://github.com/wasmino/wasmino-core). 192 | 193 | The runtime is also available at [https://github.com/wasmino/wasmino-runtime](https://github.com/wasmino/wasmino-runtime). 194 | -------------------------------------------------------------------------------- /boards.txt: -------------------------------------------------------------------------------- 1 | # See: http://code.google.com/p/arduino/wiki/Platforms 2 | 3 | menu.cpu=Processor 4 | 5 | ############################################################## 6 | 7 | wasmino.name=Wasmino 8 | wasmino.upload.using=gist 9 | wasmino.upload.protocol=gist 10 | wasmino.upload.tool=gist 11 | wasmino.upload.maximum_size=1048576 12 | wasmino.build.mcu=wasm32 13 | wasmino.build.f_cpu=0L 14 | wasmino.build.board=wasmino 15 | wasmino.build.core=wasm32 16 | wasmino.build.variant=wasmino 17 | wasmino.build.compiler.c.flags=-DWASMINO_EXT_NANOSLEEP 18 | wasmino.build.compiler.cpp.flags=-DWASMINO_EXT_NANOSLEEP 19 | wasmino.build.compiler.ld.flags= 20 | wasmino.build.compiler.binaryen_wasm_opt.flags=--asyncify 21 | wasmino.upload.wait_for_upload_port=false 22 | wasmino.upload.use_1200bps_touch=false 23 | wasmino.upload.disable_flushing=false 24 | 25 | wasmino_wasi.name=Wasmino (WASI compatible) 26 | wasmino_wasi.upload.using=gist 27 | wasmino_wasi.upload.protocol=gist 28 | wasmino_wasi.upload.tool=gist 29 | wasmino_wasi.upload.maximum_size=1048576 30 | wasmino_wasi.build.mcu=wasm32 31 | wasmino_wasi.build.f_cpu=0L 32 | wasmino_wasi.build.board=wasmino 33 | wasmino_wasi.build.core=wasm32 34 | wasmino_wasi.build.variant=wasmino_wasi 35 | wasmino_wasi.build.compiler.c.flags= 36 | wasmino_wasi.build.compiler.cpp.flags= 37 | wasmino_wasi.build.compiler.ld.flags= 38 | wasmino_wasi.build.compiler.binaryen_wasm_opt.flags= 39 | wasmino_wasi.upload.wait_for_upload_port=false 40 | wasmino_wasi.upload.use_1200bps_touch=false 41 | wasmino_wasi.upload.disable_flushing=false 42 | -------------------------------------------------------------------------------- /cores/wasm32/Arduino.h: -------------------------------------------------------------------------------- 1 | #ifndef Arduino_h 2 | #define Arduino_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "HardwareSerial.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C"{ 14 | #endif 15 | 16 | #define HIGH 0x1 17 | #define LOW 0x0 18 | 19 | #define INPUT 0x0 20 | #define OUTPUT 0x1 21 | #define INPUT_PULLUP 0x2 22 | 23 | #define PI 3.1415926535897932384626433832795 24 | #define HALF_PI 1.5707963267948966192313216916398 25 | #define TWO_PI 6.283185307179586476925286766559 26 | #define DEG_TO_RAD 0.017453292519943295769236907684886 27 | #define RAD_TO_DEG 57.295779513082320876798154814105 28 | #define EULER 2.718281828459045235360287471352 29 | 30 | #define SERIAL 0x0 31 | #define DISPLAY 0x1 32 | 33 | #define LSBFIRST 0 34 | #define MSBFIRST 1 35 | 36 | #define CHANGE 1 37 | #define FALLING 2 38 | #define RISING 3 39 | 40 | #define INTERNAL 3 41 | #define DEFAULT 1 42 | #define EXTERNAL 0 43 | 44 | // undefine stdlib's abs if encountered 45 | #ifdef abs 46 | #undef abs 47 | #endif 48 | 49 | #define min(a,b) ((a)<(b)?(a):(b)) 50 | #define max(a,b) ((a)>(b)?(a):(b)) 51 | #define abs(x) ((x)>0?(x):-(x)) 52 | #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) 53 | #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) 54 | #define radians(deg) ((deg)*DEG_TO_RAD) 55 | #define degrees(rad) ((rad)*RAD_TO_DEG) 56 | #define sq(x) ((x)*(x)) 57 | 58 | #define lowByte(w) ((uint8_t) ((w) & 0xff)) 59 | #define highByte(w) ((uint8_t) ((w) >> 8)) 60 | 61 | #define bitRead(value, bit) (((value) >> (bit)) & 0x01) 62 | #define bitSet(value, bit) ((value) |= (1UL << (bit))) 63 | #define bitClear(value, bit) ((value) &= ~(1UL << (bit))) 64 | #define bitToggle(value, bit) ((value) ^= (1UL << (bit))) 65 | #define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit)) 66 | 67 | #define digitalPinToInterrupt(pin) (pin) 68 | 69 | // avr-libc defines _NOP() since 1.6.2 70 | #ifndef _NOP 71 | #define _NOP() do { __asm__ volatile ("nop"); } while (0) 72 | #endif 73 | 74 | typedef unsigned int word; 75 | 76 | #define bit(b) (1UL << (b)) 77 | 78 | typedef bool boolean; 79 | typedef uint8_t byte; 80 | 81 | void pinMode(uint8_t pin, uint8_t mode); 82 | void digitalWrite(uint8_t pin, uint8_t val); 83 | int digitalRead(uint8_t pin); 84 | int analogRead(uint8_t pin); 85 | void analogReference(uint8_t mode); 86 | void analogWrite(uint8_t pin, int val); 87 | 88 | unsigned long millis(void); 89 | unsigned long micros(void); 90 | void delay(unsigned long ms); 91 | void delayMicroseconds(unsigned int us); 92 | 93 | void attachInterrupt(uint8_t intr, void (*isr)(), int mode); 94 | void detachInterrupt(uint8_t intr); 95 | 96 | void interrupts(); 97 | void noInterrupts(); 98 | 99 | void setup(void); 100 | void loop(void); 101 | 102 | #define NOT_A_PIN 0 103 | #define NOT_A_PORT 0 104 | 105 | #ifdef __cplusplus 106 | } // extern "C" 107 | #endif 108 | 109 | #endif 110 | -------------------------------------------------------------------------------- /cores/wasm32/HardwareSerial.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | HardwareSerial.cpp - Hardware serial library for Wiring 3 | Copyright (c) 2006 Nicholas Zambetti. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | Modified 23 November 2006 by David A. Mellis 20 | Modified 28 September 2010 by Mark Sproul 21 | Modified 14 August 2012 by Alarus 22 | Modified 3 December 2013 by Matthijs Kooijman 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "Arduino.h" 31 | 32 | #include "HardwareSerial.h" 33 | 34 | static ssize_t _write(int fd, const void *buf, size_t count) { 35 | return write(fd, buf, count); 36 | } 37 | 38 | // Public Methods ////////////////////////////////////////////////////////////// 39 | 40 | void HardwareSerial::begin(unsigned long baud, byte config) 41 | { 42 | } 43 | 44 | void HardwareSerial::end() 45 | { 46 | } 47 | 48 | int HardwareSerial::available(void) 49 | { 50 | return INT32_MAX; 51 | } 52 | 53 | int HardwareSerial::peek(void) 54 | { 55 | int c = getc(stdin); 56 | ungetc(c, stdin); 57 | return c; 58 | } 59 | 60 | int HardwareSerial::read(void) 61 | { 62 | return getc(stdin); 63 | } 64 | 65 | int HardwareSerial::availableForWrite(void) 66 | { 67 | return INT32_MAX; 68 | } 69 | 70 | void HardwareSerial::flush() 71 | { 72 | // flush to stdout. 73 | fflush(stdout); 74 | } 75 | 76 | size_t HardwareSerial::write(uint8_t c) 77 | { 78 | putc(c, stdout); 79 | return 1; 80 | } 81 | 82 | HardwareSerial Serial; 83 | -------------------------------------------------------------------------------- /cores/wasm32/HardwareSerial.h: -------------------------------------------------------------------------------- 1 | /* 2 | HardwareSerial.h - Hardware serial library for Wiring 3 | Copyright (c) 2006 Nicholas Zambetti. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | Modified 28 September 2010 by Mark Sproul 20 | Modified 14 August 2012 by Alarus 21 | Modified 3 December 2013 by Matthijs Kooijman 22 | */ 23 | 24 | #ifndef HardwareSerial_h 25 | #define HardwareSerial_h 26 | 27 | #include 28 | 29 | #include "Stream.h" 30 | 31 | #ifndef SERIAL_TX_BUFFER_SIZE 32 | #define SERIAL_TX_BUFFER_SIZE 128 33 | #endif 34 | 35 | #ifndef SERIAL_RX_BUFFER_SIZE 36 | #define SERIAL_RX_BUFFER_SIZE 128 37 | #endif 38 | 39 | // Define config for Serial.begin(baud, config); 40 | #define SERIAL_5N1 0x00 41 | #define SERIAL_6N1 0x02 42 | #define SERIAL_7N1 0x04 43 | #define SERIAL_8N1 0x06 44 | #define SERIAL_5N2 0x08 45 | #define SERIAL_6N2 0x0A 46 | #define SERIAL_7N2 0x0C 47 | #define SERIAL_8N2 0x0E 48 | #define SERIAL_5E1 0x20 49 | #define SERIAL_6E1 0x22 50 | #define SERIAL_7E1 0x24 51 | #define SERIAL_8E1 0x26 52 | #define SERIAL_5E2 0x28 53 | #define SERIAL_6E2 0x2A 54 | #define SERIAL_7E2 0x2C 55 | #define SERIAL_8E2 0x2E 56 | #define SERIAL_5O1 0x30 57 | #define SERIAL_6O1 0x32 58 | #define SERIAL_7O1 0x34 59 | #define SERIAL_8O1 0x36 60 | #define SERIAL_5O2 0x38 61 | #define SERIAL_6O2 0x3A 62 | #define SERIAL_7O2 0x3C 63 | #define SERIAL_8O2 0x3E 64 | 65 | class HardwareSerial : public Stream 66 | { 67 | public: 68 | inline HardwareSerial(){}; 69 | void begin(unsigned long baud) { begin(baud, SERIAL_8N1); } 70 | void begin(unsigned long, uint8_t); 71 | void end(); 72 | virtual int available(void); 73 | virtual int peek(void); 74 | virtual int read(void); 75 | virtual int availableForWrite(void); 76 | virtual void flush(void); 77 | virtual size_t write(uint8_t); 78 | inline size_t write(unsigned long n) { return write((uint8_t)n); } 79 | inline size_t write(long n) { return write((uint8_t)n); } 80 | inline size_t write(unsigned int n) { return write((uint8_t)n); } 81 | inline size_t write(int n) { return write((uint8_t)n); } 82 | using Print::write; // pull in write(str) and write(buf, size) from Print 83 | operator bool() { return true; } 84 | }; 85 | 86 | extern void serialEventRun(void) __attribute__((weak)); 87 | 88 | extern HardwareSerial Serial; 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /cores/wasm32/Itoa.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Itoa.h" 3 | 4 | static char num[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 5 | 6 | static void strreverse(char *begin, char *end) 7 | { 8 | char aux; 9 | 10 | while (end > begin) 11 | aux = *end, *end-- = *begin, *begin++ = aux; 12 | } 13 | 14 | char *ltoa(long value, char *str, int base) 15 | { 16 | char *wstr = str; 17 | int sign; 18 | 19 | // Validate base 20 | if (base < 2 || base > 35) 21 | { 22 | *wstr = '\0'; 23 | return str; 24 | } 25 | 26 | // Take care of sign 27 | if ((sign = value) < 0) 28 | value = -value; 29 | 30 | // Conversion. Number is reversed. 31 | do 32 | { 33 | *wstr++ = num[value % base]; 34 | } while (value /= base); 35 | 36 | if (sign < 0) 37 | *wstr++ = '-'; 38 | 39 | *wstr = '\0'; 40 | // Reverse string 41 | strreverse(str, wstr - 1); 42 | return str; 43 | } 44 | 45 | char *itoa(int value, char *str, int base) 46 | { 47 | return ltoa(value, str, base); 48 | } 49 | 50 | char *ultoa(unsigned long value, char *str, int base) 51 | { 52 | char *wstr = str; 53 | 54 | // Validate base 55 | if (base < 2 || base > 35) 56 | { 57 | *wstr = '\0'; 58 | return str; 59 | } 60 | 61 | // Conversion. Number is reversed. 62 | do 63 | { 64 | *wstr++ = num[value % base]; 65 | } while (value /= base); 66 | 67 | *wstr = '\0'; 68 | // Reverse string 69 | strreverse(str, wstr - 1); 70 | return str; 71 | } 72 | 73 | char *utoa(unsigned int value, char *str, int base) 74 | { 75 | return ultoa(value, str, base); 76 | } 77 | 78 | char *dtostrf(double value, signed char width, unsigned char prec, char *str) 79 | { 80 | sprintf(str, "%.*f", prec, value); 81 | return str; 82 | } 83 | -------------------------------------------------------------------------------- /cores/wasm32/Itoa.h: -------------------------------------------------------------------------------- 1 | #ifndef Itoa_h 2 | #define Itoa_h 3 | 4 | #ifdef __cplusplus 5 | extern "C"{ 6 | #endif 7 | 8 | char *itoa(int value, char *str, int base); 9 | char *utoa(unsigned long value, char *str, int base); 10 | 11 | char *ltoa(long value, char *str, int base); 12 | char *ultoa(unsigned long value, char *str, int base); 13 | 14 | char *dtostrf(double value, signed char width, unsigned char prec, char *str); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /cores/wasm32/Print.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Print.cpp - Base class that provides print() and println() 3 | Copyright (c) 2008 David A. Mellis. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | Modified 23 November 2006 by David A. Mellis 20 | Modified 03 August 2015 by Chuck Todd 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "Arduino.h" 28 | 29 | #include "Print.h" 30 | 31 | // Public Methods ////////////////////////////////////////////////////////////// 32 | 33 | /* default implementation: may be overridden */ 34 | size_t Print::write(const uint8_t *buffer, size_t size) 35 | { 36 | size_t n = 0; 37 | while (size--) { 38 | if (write(*buffer++)) n++; 39 | else break; 40 | } 41 | return n; 42 | } 43 | 44 | size_t Print::print(const String &s) 45 | { 46 | return write(s.c_str(), s.length()); 47 | } 48 | 49 | size_t Print::print(const char str[]) 50 | { 51 | return write(str); 52 | } 53 | 54 | size_t Print::print(char c) 55 | { 56 | return write(c); 57 | } 58 | 59 | size_t Print::print(unsigned char b, int base) 60 | { 61 | return print((unsigned long) b, base); 62 | } 63 | 64 | size_t Print::print(int n, int base) 65 | { 66 | return print((long) n, base); 67 | } 68 | 69 | size_t Print::print(unsigned int n, int base) 70 | { 71 | return print((unsigned long) n, base); 72 | } 73 | 74 | size_t Print::print(long n, int base) 75 | { 76 | if (base == 0) { 77 | return write(n); 78 | } else if (base == 10) { 79 | if (n < 0) { 80 | int t = print('-'); 81 | n = -n; 82 | return printNumber(n, 10) + t; 83 | } 84 | return printNumber(n, 10); 85 | } else { 86 | return printNumber(n, base); 87 | } 88 | } 89 | 90 | size_t Print::print(unsigned long n, int base) 91 | { 92 | if (base == 0) return write(n); 93 | else return printNumber(n, base); 94 | } 95 | 96 | size_t Print::print(double n, int digits) 97 | { 98 | return printFloat(n, digits); 99 | } 100 | 101 | size_t Print::print(const Printable& x) 102 | { 103 | return x.printTo(*this); 104 | } 105 | 106 | size_t Print::println(void) 107 | { 108 | return write("\r\n"); 109 | } 110 | 111 | size_t Print::println(const String &s) 112 | { 113 | size_t n = print(s); 114 | n += println(); 115 | return n; 116 | } 117 | 118 | size_t Print::println(const char c[]) 119 | { 120 | size_t n = print(c); 121 | n += println(); 122 | return n; 123 | } 124 | 125 | size_t Print::println(char c) 126 | { 127 | size_t n = print(c); 128 | n += println(); 129 | return n; 130 | } 131 | 132 | size_t Print::println(unsigned char b, int base) 133 | { 134 | size_t n = print(b, base); 135 | n += println(); 136 | return n; 137 | } 138 | 139 | size_t Print::println(int num, int base) 140 | { 141 | size_t n = print(num, base); 142 | n += println(); 143 | return n; 144 | } 145 | 146 | size_t Print::println(unsigned int num, int base) 147 | { 148 | size_t n = print(num, base); 149 | n += println(); 150 | return n; 151 | } 152 | 153 | size_t Print::println(long num, int base) 154 | { 155 | size_t n = print(num, base); 156 | n += println(); 157 | return n; 158 | } 159 | 160 | size_t Print::println(unsigned long num, int base) 161 | { 162 | size_t n = print(num, base); 163 | n += println(); 164 | return n; 165 | } 166 | 167 | size_t Print::println(double num, int digits) 168 | { 169 | size_t n = print(num, digits); 170 | n += println(); 171 | return n; 172 | } 173 | 174 | size_t Print::println(const Printable& x) 175 | { 176 | size_t n = print(x); 177 | n += println(); 178 | return n; 179 | } 180 | 181 | // Private Methods ///////////////////////////////////////////////////////////// 182 | 183 | size_t Print::printNumber(unsigned long n, uint8_t base) 184 | { 185 | char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. 186 | char *str = &buf[sizeof(buf) - 1]; 187 | 188 | *str = '\0'; 189 | 190 | // prevent crash if called with base == 1 191 | if (base < 2) base = 10; 192 | 193 | do { 194 | char c = n % base; 195 | n /= base; 196 | 197 | *--str = c < 10 ? c + '0' : c + 'A' - 10; 198 | } while(n); 199 | 200 | return write(str); 201 | } 202 | 203 | size_t Print::printFloat(double number, uint8_t digits) 204 | { 205 | size_t n = 0; 206 | 207 | if (isnan(number)) return print("nan"); 208 | if (isinf(number)) return print("inf"); 209 | if (number > 4294967040.0) return print ("ovf"); // constant determined empirically 210 | if (number <-4294967040.0) return print ("ovf"); // constant determined empirically 211 | 212 | // Handle negative numbers 213 | if (number < 0.0) 214 | { 215 | n += print('-'); 216 | number = -number; 217 | } 218 | 219 | // Round correctly so that print(1.999, 2) prints as "2.00" 220 | double rounding = 0.5; 221 | for (uint8_t i=0; i 0) { 233 | n += print('.'); 234 | } 235 | 236 | // Extract digits from the remainder one at a time 237 | while (digits-- > 0) 238 | { 239 | remainder *= 10.0; 240 | unsigned int toPrint = (unsigned int)(remainder); 241 | n += print(toPrint); 242 | remainder -= toPrint; 243 | } 244 | 245 | return n; 246 | } 247 | -------------------------------------------------------------------------------- /cores/wasm32/Print.h: -------------------------------------------------------------------------------- 1 | /* 2 | Print.h - Base class that provides print() and println() 3 | Copyright (c) 2008 David A. Mellis. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef Print_h 21 | #define Print_h 22 | 23 | #include 24 | #include // for size_t 25 | 26 | #include "WString.h" 27 | #include "Printable.h" 28 | 29 | #define DEC 10 30 | #define HEX 16 31 | #define OCT 8 32 | #ifdef BIN // Prevent warnings if BIN is previously defined in "iotnx4.h" or similar 33 | #undef BIN 34 | #endif 35 | #define BIN 2 36 | 37 | class Print 38 | { 39 | private: 40 | int write_error; 41 | size_t printNumber(unsigned long, uint8_t); 42 | size_t printFloat(double, uint8_t); 43 | protected: 44 | void setWriteError(int err = 1) { write_error = err; } 45 | public: 46 | Print() : write_error(0) {} 47 | 48 | int getWriteError() { return write_error; } 49 | void clearWriteError() { setWriteError(0); } 50 | 51 | virtual size_t write(uint8_t) = 0; 52 | size_t write(const char *str) { 53 | if (str == NULL) return 0; 54 | return write((const uint8_t *)str, strlen(str)); 55 | } 56 | virtual size_t write(const uint8_t *buffer, size_t size); 57 | size_t write(const char *buffer, size_t size) { 58 | return write((const uint8_t *)buffer, size); 59 | } 60 | 61 | // default to zero, meaning "a single write may block" 62 | // should be overriden by subclasses with buffering 63 | virtual int availableForWrite() { return 0; } 64 | 65 | size_t print(const String &); 66 | size_t print(const char[]); 67 | size_t print(char); 68 | size_t print(unsigned char, int = DEC); 69 | size_t print(int, int = DEC); 70 | size_t print(unsigned int, int = DEC); 71 | size_t print(long, int = DEC); 72 | size_t print(unsigned long, int = DEC); 73 | size_t print(double, int = 2); 74 | size_t print(const Printable&); 75 | 76 | size_t println(const String &s); 77 | size_t println(const char[]); 78 | size_t println(char); 79 | size_t println(unsigned char, int = DEC); 80 | size_t println(int, int = DEC); 81 | size_t println(unsigned int, int = DEC); 82 | size_t println(long, int = DEC); 83 | size_t println(unsigned long, int = DEC); 84 | size_t println(double, int = 2); 85 | size_t println(const Printable&); 86 | size_t println(void); 87 | 88 | virtual void flush() { /* Empty implementation for backward compatibility */ } 89 | }; 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /cores/wasm32/Printable.h: -------------------------------------------------------------------------------- 1 | /* 2 | Printable.h - Interface class that allows printing of complex types 3 | Copyright (c) 2011 Adrian McEwen. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef Printable_h 21 | #define Printable_h 22 | 23 | #include 24 | 25 | class Print; 26 | 27 | /** The Printable class provides a way for new classes to allow themselves to be printed. 28 | By deriving from Printable and implementing the printTo method, it will then be possible 29 | for users to print out instances of this class by passing them into the usual 30 | Print::print and Print::println methods. 31 | */ 32 | 33 | class Printable 34 | { 35 | public: 36 | virtual size_t printTo(Print& p) const = 0; 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /cores/wasm32/Stream.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stream.cpp - adds parsing methods to Stream class 3 | Copyright (c) 2008 David A. Mellis. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | Created July 2011 20 | parsing functions based on TextFinder library by Michael Margolis 21 | 22 | findMulti/findUntil routines written by Jim Leonard/Xuth 23 | */ 24 | 25 | #include "Arduino.h" 26 | #include "Stream.h" 27 | 28 | #define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait 29 | 30 | // protected method to read stream with timeout 31 | int Stream::timedRead() 32 | { 33 | int c; 34 | _startMillis = millis(); 35 | do { 36 | c = read(); 37 | if (c >= 0) return c; 38 | } while(millis() - _startMillis < _timeout); 39 | return -1; // -1 indicates timeout 40 | } 41 | 42 | // protected method to peek stream with timeout 43 | int Stream::timedPeek() 44 | { 45 | int c; 46 | _startMillis = millis(); 47 | do { 48 | c = peek(); 49 | if (c >= 0) return c; 50 | } while(millis() - _startMillis < _timeout); 51 | return -1; // -1 indicates timeout 52 | } 53 | 54 | // returns peek of the next digit in the stream or -1 if timeout 55 | // discards non-numeric characters 56 | int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal) 57 | { 58 | int c; 59 | while (1) { 60 | c = timedPeek(); 61 | 62 | if( c < 0 || 63 | c == '-' || 64 | (c >= '0' && c <= '9') || 65 | (detectDecimal && c == '.')) return c; 66 | 67 | switch( lookahead ){ 68 | case SKIP_NONE: return -1; // Fail code. 69 | case SKIP_WHITESPACE: 70 | switch( c ){ 71 | case ' ': 72 | case '\t': 73 | case '\r': 74 | case '\n': break; 75 | default: return -1; // Fail code. 76 | } 77 | case SKIP_ALL: 78 | break; 79 | } 80 | read(); // discard non-numeric 81 | } 82 | } 83 | 84 | // Public Methods 85 | ////////////////////////////////////////////////////////////// 86 | 87 | void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait 88 | { 89 | _timeout = timeout; 90 | } 91 | 92 | // find returns true if the target string is found 93 | bool Stream::find(char *target) 94 | { 95 | return findUntil(target, strlen(target), NULL, 0); 96 | } 97 | 98 | // reads data from the stream until the target string of given length is found 99 | // returns true if target string is found, false if timed out 100 | bool Stream::find(char *target, size_t length) 101 | { 102 | return findUntil(target, length, NULL, 0); 103 | } 104 | 105 | // as find but search ends if the terminator string is found 106 | bool Stream::findUntil(char *target, char *terminator) 107 | { 108 | return findUntil(target, strlen(target), terminator, strlen(terminator)); 109 | } 110 | 111 | // reads data from the stream until the target string of the given length is found 112 | // search terminated if the terminator string is found 113 | // returns true if target string is found, false if terminated or timed out 114 | bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen) 115 | { 116 | if (terminator == NULL) { 117 | MultiTarget t[1] = {{target, targetLen, 0}}; 118 | return findMulti(t, 1) == 0 ? true : false; 119 | } else { 120 | MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}}; 121 | return findMulti(t, 2) == 0 ? true : false; 122 | } 123 | } 124 | 125 | // returns the first valid (long) integer value from the current position. 126 | // lookahead determines how parseInt looks ahead in the stream. 127 | // See LookaheadMode enumeration at the top of the file. 128 | // Lookahead is terminated by the first character that is not a valid part of an integer. 129 | // Once parsing commences, 'ignore' will be skipped in the stream. 130 | long Stream::parseInt(LookaheadMode lookahead, char ignore) 131 | { 132 | bool isNegative = false; 133 | long value = 0; 134 | int c; 135 | 136 | c = peekNextDigit(lookahead, false); 137 | // ignore non numeric leading characters 138 | if(c < 0) 139 | return 0; // zero returned if timeout 140 | 141 | do{ 142 | if(c == ignore) 143 | ; // ignore this character 144 | else if(c == '-') 145 | isNegative = true; 146 | else if(c >= '0' && c <= '9') // is c a digit? 147 | value = value * 10 + c - '0'; 148 | read(); // consume the character we got with peek 149 | c = timedPeek(); 150 | } 151 | while( (c >= '0' && c <= '9') || c == ignore ); 152 | 153 | if(isNegative) 154 | value = -value; 155 | return value; 156 | } 157 | 158 | // as parseInt but returns a floating point value 159 | float Stream::parseFloat(LookaheadMode lookahead, char ignore) 160 | { 161 | bool isNegative = false; 162 | bool isFraction = false; 163 | long value = 0; 164 | int c; 165 | float fraction = 1.0; 166 | 167 | c = peekNextDigit(lookahead, true); 168 | // ignore non numeric leading characters 169 | if(c < 0) 170 | return 0; // zero returned if timeout 171 | 172 | do{ 173 | if(c == ignore) 174 | ; // ignore 175 | else if(c == '-') 176 | isNegative = true; 177 | else if (c == '.') 178 | isFraction = true; 179 | else if(c >= '0' && c <= '9') { // is c a digit? 180 | value = value * 10 + c - '0'; 181 | if(isFraction) 182 | fraction *= 0.1; 183 | } 184 | read(); // consume the character we got with peek 185 | c = timedPeek(); 186 | } 187 | while( (c >= '0' && c <= '9') || (c == '.' && !isFraction) || c == ignore ); 188 | 189 | if(isNegative) 190 | value = -value; 191 | if(isFraction) 192 | return value * fraction; 193 | else 194 | return value; 195 | } 196 | 197 | // read characters from stream into buffer 198 | // terminates if length characters have been read, or timeout (see setTimeout) 199 | // returns the number of characters placed in the buffer 200 | // the buffer is NOT null terminated. 201 | // 202 | size_t Stream::readBytes(char *buffer, size_t length) 203 | { 204 | size_t count = 0; 205 | while (count < length) { 206 | int c = timedRead(); 207 | if (c < 0) break; 208 | *buffer++ = (char)c; 209 | count++; 210 | } 211 | return count; 212 | } 213 | 214 | 215 | // as readBytes with terminator character 216 | // terminates if length characters have been read, timeout, or if the terminator character detected 217 | // returns the number of characters placed in the buffer (0 means no valid data found) 218 | 219 | size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) 220 | { 221 | size_t index = 0; 222 | while (index < length) { 223 | int c = timedRead(); 224 | if (c < 0 || c == terminator) break; 225 | *buffer++ = (char)c; 226 | index++; 227 | } 228 | return index; // return number of characters, not including null terminator 229 | } 230 | 231 | String Stream::readString() 232 | { 233 | String ret; 234 | int c = timedRead(); 235 | while (c >= 0) 236 | { 237 | ret += (char)c; 238 | c = timedRead(); 239 | } 240 | return ret; 241 | } 242 | 243 | String Stream::readStringUntil(char terminator) 244 | { 245 | String ret; 246 | int c = timedRead(); 247 | while (c >= 0 && c != terminator) 248 | { 249 | ret += (char)c; 250 | c = timedRead(); 251 | } 252 | return ret; 253 | } 254 | 255 | int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { 256 | // any zero length target string automatically matches and would make 257 | // a mess of the rest of the algorithm. 258 | for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { 259 | if (t->len <= 0) 260 | return t - targets; 261 | } 262 | 263 | while (1) { 264 | int c = timedRead(); 265 | if (c < 0) 266 | return -1; 267 | 268 | for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { 269 | // the simple case is if we match, deal with that first. 270 | if (c == t->str[t->index]) { 271 | if (++t->index == t->len) 272 | return t - targets; 273 | else 274 | continue; 275 | } 276 | 277 | // if not we need to walk back and see if we could have matched further 278 | // down the stream (ie '1112' doesn't match the first position in '11112' 279 | // but it will match the second position so we can't just reset the current 280 | // index to 0 when we find a mismatch. 281 | if (t->index == 0) 282 | continue; 283 | 284 | int origIndex = t->index; 285 | do { 286 | --t->index; 287 | // first check if current char works against the new current index 288 | if (c != t->str[t->index]) 289 | continue; 290 | 291 | // if it's the only char then we're good, nothing more to check 292 | if (t->index == 0) { 293 | t->index++; 294 | break; 295 | } 296 | 297 | // otherwise we need to check the rest of the found string 298 | int diff = origIndex - t->index; 299 | size_t i; 300 | for (i = 0; i < t->index; ++i) { 301 | if (t->str[i] != t->str[i + diff]) 302 | break; 303 | } 304 | 305 | // if we successfully got through the previous loop then our current 306 | // index is good. 307 | if (i == t->index) { 308 | t->index++; 309 | break; 310 | } 311 | 312 | // otherwise we just try the next index 313 | } while (t->index); 314 | } 315 | } 316 | // unreachable 317 | return -1; 318 | } 319 | -------------------------------------------------------------------------------- /cores/wasm32/Stream.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stream.h - base class for character-based streams. 3 | Copyright (c) 2010 David A. Mellis. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | parsing functions based on TextFinder library by Michael Margolis 20 | */ 21 | 22 | #ifndef Stream_h 23 | #define Stream_h 24 | 25 | #include 26 | #include "Print.h" 27 | 28 | // compatability macros for testing 29 | /* 30 | #define getInt() parseInt() 31 | #define getInt(ignore) parseInt(ignore) 32 | #define getFloat() parseFloat() 33 | #define getFloat(ignore) parseFloat(ignore) 34 | #define getString( pre_string, post_string, buffer, length) 35 | readBytesBetween( pre_string, terminator, buffer, length) 36 | */ 37 | 38 | // This enumeration provides the lookahead options for parseInt(), parseFloat() 39 | // The rules set out here are used until either the first valid character is found 40 | // or a time out occurs due to lack of input. 41 | enum LookaheadMode{ 42 | SKIP_ALL, // All invalid characters are ignored. 43 | SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid. 44 | SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped. 45 | }; 46 | 47 | #define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field 48 | 49 | class Stream : public Print 50 | { 51 | protected: 52 | unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read 53 | unsigned long _startMillis; // used for timeout measurement 54 | int timedRead(); // read stream with timeout 55 | int timedPeek(); // peek stream with timeout 56 | int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout 57 | 58 | public: 59 | virtual int available() = 0; 60 | virtual int read() = 0; 61 | virtual int peek() = 0; 62 | 63 | Stream() {_timeout=1000;} 64 | 65 | // parsing methods 66 | 67 | void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second 68 | unsigned long getTimeout(void) { return _timeout; } 69 | 70 | bool find(char *target); // reads data from the stream until the target string is found 71 | bool find(uint8_t *target) { return find ((char *)target); } 72 | // returns true if target string is found, false if timed out (see setTimeout) 73 | 74 | bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found 75 | bool find(uint8_t *target, size_t length) { return find ((char *)target, length); } 76 | // returns true if target string is found, false if timed out 77 | 78 | bool find(char target) { return find (&target, 1); } 79 | 80 | bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found 81 | bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); } 82 | 83 | bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found 84 | bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); } 85 | 86 | long parseInt(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); 87 | // returns the first valid (long) integer value from the current position. 88 | // lookahead determines how parseInt looks ahead in the stream. 89 | // See LookaheadMode enumeration at the top of the file. 90 | // Lookahead is terminated by the first character that is not a valid part of an integer. 91 | // Once parsing commences, 'ignore' will be skipped in the stream. 92 | 93 | float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); 94 | // float version of parseInt 95 | 96 | size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer 97 | size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); } 98 | // terminates if length characters have been read or timeout (see setTimeout) 99 | // returns the number of characters placed in the buffer (0 means no valid data found) 100 | 101 | size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character 102 | size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); } 103 | // terminates if length characters have been read, timeout, or if the terminator character detected 104 | // returns the number of characters placed in the buffer (0 means no valid data found) 105 | 106 | // Arduino String functions to be added here 107 | String readString(); 108 | String readStringUntil(char terminator); 109 | 110 | protected: 111 | long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); } 112 | float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); } 113 | // These overload exists for compatibility with any class that has derived 114 | // Stream and used parseFloat/Int with a custom ignore character. To keep 115 | // the public API simple, these overload remains protected. 116 | 117 | struct MultiTarget { 118 | const char *str; // string you're searching for 119 | size_t len; // length of string you're searching for 120 | size_t index; // index used by the search routine. 121 | }; 122 | 123 | // This allows you to search for an arbitrary number of strings. 124 | // Returns index of the target that is found first or -1 if timeout occurs. 125 | int findMulti(struct MultiTarget *targets, int tCount); 126 | }; 127 | 128 | #undef NO_IGNORE_CHAR 129 | #endif 130 | -------------------------------------------------------------------------------- /cores/wasm32/WString.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WString.cpp - String library for Wiring & Arduino 3 | ...mostly rewritten by Paul Stoffregen... 4 | Copyright (c) 2009-10 Hernando Barragan. All rights reserved. 5 | Copyright 2011, Paul Stoffregen, paul@pjrc.com 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include "WString.h" 23 | 24 | /*********************************************/ 25 | /* Constructors */ 26 | /*********************************************/ 27 | 28 | String::String(const char *cstr) 29 | { 30 | init(); 31 | if (cstr) 32 | copy(cstr, strlen(cstr)); 33 | } 34 | 35 | String::String(const String &value) 36 | { 37 | init(); 38 | *this = value; 39 | } 40 | 41 | #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) 42 | String::String(String &&rval) 43 | { 44 | init(); 45 | move(rval); 46 | } 47 | String::String(StringSumHelper &&rval) 48 | { 49 | init(); 50 | move(rval); 51 | } 52 | #endif 53 | 54 | String::String(char c) 55 | { 56 | init(); 57 | char buf[2]; 58 | buf[0] = c; 59 | buf[1] = 0; 60 | *this = buf; 61 | } 62 | 63 | String::String(unsigned char value, unsigned char base) 64 | { 65 | init(); 66 | char buf[1 + 8 * sizeof(unsigned char)]; 67 | utoa(value, buf, base); 68 | *this = buf; 69 | } 70 | 71 | String::String(int value, unsigned char base) 72 | { 73 | init(); 74 | char buf[2 + 8 * sizeof(int)]; 75 | itoa(value, buf, base); 76 | *this = buf; 77 | } 78 | 79 | String::String(unsigned int value, unsigned char base) 80 | { 81 | init(); 82 | char buf[1 + 8 * sizeof(unsigned int)]; 83 | utoa(value, buf, base); 84 | *this = buf; 85 | } 86 | 87 | String::String(long value, unsigned char base) 88 | { 89 | init(); 90 | char buf[2 + 8 * sizeof(long)]; 91 | ltoa(value, buf, base); 92 | *this = buf; 93 | } 94 | 95 | String::String(unsigned long value, unsigned char base) 96 | { 97 | init(); 98 | char buf[1 + 8 * sizeof(unsigned long)]; 99 | ultoa(value, buf, base); 100 | *this = buf; 101 | } 102 | 103 | String::String(float value, unsigned char decimalPlaces) 104 | { 105 | init(); 106 | char buf[33]; 107 | *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); 108 | } 109 | 110 | String::String(double value, unsigned char decimalPlaces) 111 | { 112 | init(); 113 | char buf[33]; 114 | *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); 115 | } 116 | 117 | String::~String() 118 | { 119 | if (buffer) 120 | free(buffer); 121 | } 122 | 123 | /*********************************************/ 124 | /* Memory Management */ 125 | /*********************************************/ 126 | 127 | inline void String::init(void) 128 | { 129 | buffer = NULL; 130 | capacity = 0; 131 | len = 0; 132 | } 133 | 134 | void String::invalidate(void) 135 | { 136 | if (buffer) 137 | free(buffer); 138 | buffer = NULL; 139 | capacity = len = 0; 140 | } 141 | 142 | unsigned char String::reserve(unsigned int size) 143 | { 144 | if (buffer && capacity >= size) 145 | return 1; 146 | if (changeBuffer(size)) 147 | { 148 | if (len == 0) 149 | buffer[0] = 0; 150 | return 1; 151 | } 152 | return 0; 153 | } 154 | 155 | unsigned char String::changeBuffer(unsigned int maxStrLen) 156 | { 157 | char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); 158 | if (newbuffer) 159 | { 160 | buffer = newbuffer; 161 | capacity = maxStrLen; 162 | return 1; 163 | } 164 | return 0; 165 | } 166 | 167 | /*********************************************/ 168 | /* Copy and Move */ 169 | /*********************************************/ 170 | 171 | String &String::copy(const char *cstr, unsigned int length) 172 | { 173 | if (!reserve(length)) 174 | { 175 | invalidate(); 176 | return *this; 177 | } 178 | len = length; 179 | strcpy(buffer, cstr); 180 | return *this; 181 | } 182 | 183 | #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) 184 | void String::move(String &rhs) 185 | { 186 | if (buffer) 187 | { 188 | if (rhs && capacity >= rhs.len) 189 | { 190 | strcpy(buffer, rhs.buffer); 191 | len = rhs.len; 192 | rhs.len = 0; 193 | return; 194 | } 195 | else 196 | { 197 | free(buffer); 198 | } 199 | } 200 | buffer = rhs.buffer; 201 | capacity = rhs.capacity; 202 | len = rhs.len; 203 | rhs.buffer = NULL; 204 | rhs.capacity = 0; 205 | rhs.len = 0; 206 | } 207 | #endif 208 | 209 | String &String::operator=(const String &rhs) 210 | { 211 | if (this == &rhs) 212 | return *this; 213 | 214 | if (rhs.buffer) 215 | copy(rhs.buffer, rhs.len); 216 | else 217 | invalidate(); 218 | 219 | return *this; 220 | } 221 | 222 | #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) 223 | String &String::operator=(String &&rval) 224 | { 225 | if (this != &rval) 226 | move(rval); 227 | return *this; 228 | } 229 | 230 | String &String::operator=(StringSumHelper &&rval) 231 | { 232 | if (this != &rval) 233 | move(rval); 234 | return *this; 235 | } 236 | #endif 237 | 238 | String &String::operator=(const char *cstr) 239 | { 240 | if (cstr) 241 | copy(cstr, strlen(cstr)); 242 | else 243 | invalidate(); 244 | 245 | return *this; 246 | } 247 | 248 | /*********************************************/ 249 | /* concat */ 250 | /*********************************************/ 251 | 252 | unsigned char String::concat(const String &s) 253 | { 254 | return concat(s.buffer, s.len); 255 | } 256 | 257 | unsigned char String::concat(const char *cstr, unsigned int length) 258 | { 259 | unsigned int newlen = len + length; 260 | if (!cstr) 261 | return 0; 262 | if (length == 0) 263 | return 1; 264 | if (!reserve(newlen)) 265 | return 0; 266 | strcpy(buffer + len, cstr); 267 | len = newlen; 268 | return 1; 269 | } 270 | 271 | unsigned char String::concat(const char *cstr) 272 | { 273 | if (!cstr) 274 | return 0; 275 | return concat(cstr, strlen(cstr)); 276 | } 277 | 278 | unsigned char String::concat(char c) 279 | { 280 | char buf[2]; 281 | buf[0] = c; 282 | buf[1] = 0; 283 | return concat(buf, 1); 284 | } 285 | 286 | unsigned char String::concat(unsigned char num) 287 | { 288 | char buf[1 + 3 * sizeof(unsigned char)]; 289 | itoa(num, buf, 10); 290 | return concat(buf, strlen(buf)); 291 | } 292 | 293 | unsigned char String::concat(int num) 294 | { 295 | char buf[2 + 3 * sizeof(int)]; 296 | itoa(num, buf, 10); 297 | return concat(buf, strlen(buf)); 298 | } 299 | 300 | unsigned char String::concat(unsigned int num) 301 | { 302 | char buf[1 + 3 * sizeof(unsigned int)]; 303 | utoa(num, buf, 10); 304 | return concat(buf, strlen(buf)); 305 | } 306 | 307 | unsigned char String::concat(long num) 308 | { 309 | char buf[2 + 3 * sizeof(long)]; 310 | ltoa(num, buf, 10); 311 | return concat(buf, strlen(buf)); 312 | } 313 | 314 | unsigned char String::concat(unsigned long num) 315 | { 316 | char buf[1 + 3 * sizeof(unsigned long)]; 317 | ultoa(num, buf, 10); 318 | return concat(buf, strlen(buf)); 319 | } 320 | 321 | unsigned char String::concat(float num) 322 | { 323 | char buf[20]; 324 | char *string = dtostrf(num, 4, 2, buf); 325 | return concat(string, strlen(string)); 326 | } 327 | 328 | unsigned char String::concat(double num) 329 | { 330 | char buf[20]; 331 | char *string = dtostrf(num, 4, 2, buf); 332 | return concat(string, strlen(string)); 333 | } 334 | 335 | /*********************************************/ 336 | /* Concatenate */ 337 | /*********************************************/ 338 | 339 | StringSumHelper &operator+(const StringSumHelper &lhs, const String &rhs) 340 | { 341 | StringSumHelper &a = const_cast(lhs); 342 | if (!a.concat(rhs.buffer, rhs.len)) 343 | a.invalidate(); 344 | return a; 345 | } 346 | 347 | StringSumHelper &operator+(const StringSumHelper &lhs, const char *cstr) 348 | { 349 | StringSumHelper &a = const_cast(lhs); 350 | if (!cstr || !a.concat(cstr, strlen(cstr))) 351 | a.invalidate(); 352 | return a; 353 | } 354 | 355 | StringSumHelper &operator+(const StringSumHelper &lhs, char c) 356 | { 357 | StringSumHelper &a = const_cast(lhs); 358 | if (!a.concat(c)) 359 | a.invalidate(); 360 | return a; 361 | } 362 | 363 | StringSumHelper &operator+(const StringSumHelper &lhs, unsigned char num) 364 | { 365 | StringSumHelper &a = const_cast(lhs); 366 | if (!a.concat(num)) 367 | a.invalidate(); 368 | return a; 369 | } 370 | 371 | StringSumHelper &operator+(const StringSumHelper &lhs, int num) 372 | { 373 | StringSumHelper &a = const_cast(lhs); 374 | if (!a.concat(num)) 375 | a.invalidate(); 376 | return a; 377 | } 378 | 379 | StringSumHelper &operator+(const StringSumHelper &lhs, unsigned int num) 380 | { 381 | StringSumHelper &a = const_cast(lhs); 382 | if (!a.concat(num)) 383 | a.invalidate(); 384 | return a; 385 | } 386 | 387 | StringSumHelper &operator+(const StringSumHelper &lhs, long num) 388 | { 389 | StringSumHelper &a = const_cast(lhs); 390 | if (!a.concat(num)) 391 | a.invalidate(); 392 | return a; 393 | } 394 | 395 | StringSumHelper &operator+(const StringSumHelper &lhs, unsigned long num) 396 | { 397 | StringSumHelper &a = const_cast(lhs); 398 | if (!a.concat(num)) 399 | a.invalidate(); 400 | return a; 401 | } 402 | 403 | StringSumHelper &operator+(const StringSumHelper &lhs, float num) 404 | { 405 | StringSumHelper &a = const_cast(lhs); 406 | if (!a.concat(num)) 407 | a.invalidate(); 408 | return a; 409 | } 410 | 411 | StringSumHelper &operator+(const StringSumHelper &lhs, double num) 412 | { 413 | StringSumHelper &a = const_cast(lhs); 414 | if (!a.concat(num)) 415 | a.invalidate(); 416 | return a; 417 | } 418 | 419 | /*********************************************/ 420 | /* Comparison */ 421 | /*********************************************/ 422 | 423 | int String::compareTo(const String &s) const 424 | { 425 | if (!buffer || !s.buffer) 426 | { 427 | if (s.buffer && s.len > 0) 428 | return 0 - *(unsigned char *)s.buffer; 429 | if (buffer && len > 0) 430 | return *(unsigned char *)buffer; 431 | return 0; 432 | } 433 | return strcmp(buffer, s.buffer); 434 | } 435 | 436 | unsigned char String::equals(const String &s2) const 437 | { 438 | return (len == s2.len && compareTo(s2) == 0); 439 | } 440 | 441 | unsigned char String::equals(const char *cstr) const 442 | { 443 | if (len == 0) 444 | return (cstr == NULL || *cstr == 0); 445 | if (cstr == NULL) 446 | return buffer[0] == 0; 447 | return strcmp(buffer, cstr) == 0; 448 | } 449 | 450 | unsigned char String::operator<(const String &rhs) const 451 | { 452 | return compareTo(rhs) < 0; 453 | } 454 | 455 | unsigned char String::operator>(const String &rhs) const 456 | { 457 | return compareTo(rhs) > 0; 458 | } 459 | 460 | unsigned char String::operator<=(const String &rhs) const 461 | { 462 | return compareTo(rhs) <= 0; 463 | } 464 | 465 | unsigned char String::operator>=(const String &rhs) const 466 | { 467 | return compareTo(rhs) >= 0; 468 | } 469 | 470 | unsigned char String::equalsIgnoreCase(const String &s2) const 471 | { 472 | if (this == &s2) 473 | return 1; 474 | if (len != s2.len) 475 | return 0; 476 | if (len == 0) 477 | return 1; 478 | const char *p1 = buffer; 479 | const char *p2 = s2.buffer; 480 | while (*p1) 481 | { 482 | if (tolower(*p1++) != tolower(*p2++)) 483 | return 0; 484 | } 485 | return 1; 486 | } 487 | 488 | unsigned char String::startsWith(const String &s2) const 489 | { 490 | if (len < s2.len) 491 | return 0; 492 | return startsWith(s2, 0); 493 | } 494 | 495 | unsigned char String::startsWith(const String &s2, unsigned int offset) const 496 | { 497 | if (offset > len - s2.len || !buffer || !s2.buffer) 498 | return 0; 499 | return strncmp(&buffer[offset], s2.buffer, s2.len) == 0; 500 | } 501 | 502 | unsigned char String::endsWith(const String &s2) const 503 | { 504 | if (len < s2.len || !buffer || !s2.buffer) 505 | return 0; 506 | return strcmp(&buffer[len - s2.len], s2.buffer) == 0; 507 | } 508 | 509 | /*********************************************/ 510 | /* Character Access */ 511 | /*********************************************/ 512 | 513 | char String::charAt(unsigned int loc) const 514 | { 515 | return operator[](loc); 516 | } 517 | 518 | void String::setCharAt(unsigned int loc, char c) 519 | { 520 | if (loc < len) 521 | buffer[loc] = c; 522 | } 523 | 524 | char &String::operator[](unsigned int index) 525 | { 526 | static char dummy_writable_char; 527 | if (index >= len || !buffer) 528 | { 529 | dummy_writable_char = 0; 530 | return dummy_writable_char; 531 | } 532 | return buffer[index]; 533 | } 534 | 535 | char String::operator[](unsigned int index) const 536 | { 537 | if (index >= len || !buffer) 538 | return 0; 539 | return buffer[index]; 540 | } 541 | 542 | void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const 543 | { 544 | if (!bufsize || !buf) 545 | return; 546 | if (index >= len) 547 | { 548 | buf[0] = 0; 549 | return; 550 | } 551 | unsigned int n = bufsize - 1; 552 | if (n > len - index) 553 | n = len - index; 554 | strncpy((char *)buf, buffer + index, n); 555 | buf[n] = 0; 556 | } 557 | 558 | /*********************************************/ 559 | /* Search */ 560 | /*********************************************/ 561 | 562 | int String::indexOf(char c) const 563 | { 564 | return indexOf(c, 0); 565 | } 566 | 567 | int String::indexOf(char ch, unsigned int fromIndex) const 568 | { 569 | if (fromIndex >= len) 570 | return -1; 571 | const char *temp = strchr(buffer + fromIndex, ch); 572 | if (temp == NULL) 573 | return -1; 574 | return temp - buffer; 575 | } 576 | 577 | int String::indexOf(const String &s2) const 578 | { 579 | return indexOf(s2, 0); 580 | } 581 | 582 | int String::indexOf(const String &s2, unsigned int fromIndex) const 583 | { 584 | if (fromIndex >= len) 585 | return -1; 586 | const char *found = strstr(buffer + fromIndex, s2.buffer); 587 | if (found == NULL) 588 | return -1; 589 | return found - buffer; 590 | } 591 | 592 | int String::lastIndexOf(char theChar) const 593 | { 594 | return lastIndexOf(theChar, len - 1); 595 | } 596 | 597 | int String::lastIndexOf(char ch, unsigned int fromIndex) const 598 | { 599 | if (fromIndex >= len) 600 | return -1; 601 | char tempchar = buffer[fromIndex + 1]; 602 | buffer[fromIndex + 1] = '\0'; 603 | char *temp = strrchr(buffer, ch); 604 | buffer[fromIndex + 1] = tempchar; 605 | if (temp == NULL) 606 | return -1; 607 | return temp - buffer; 608 | } 609 | 610 | int String::lastIndexOf(const String &s2) const 611 | { 612 | return lastIndexOf(s2, len - s2.len); 613 | } 614 | 615 | int String::lastIndexOf(const String &s2, unsigned int fromIndex) const 616 | { 617 | if (s2.len == 0 || len == 0 || s2.len > len) 618 | return -1; 619 | if (fromIndex >= len) 620 | fromIndex = len - 1; 621 | int found = -1; 622 | for (char *p = buffer; p <= buffer + fromIndex; p++) 623 | { 624 | p = strstr(p, s2.buffer); 625 | if (!p) 626 | break; 627 | if ((unsigned int)(p - buffer) <= fromIndex) 628 | found = p - buffer; 629 | } 630 | return found; 631 | } 632 | 633 | String String::substring(unsigned int left, unsigned int right) const 634 | { 635 | if (left > right) 636 | { 637 | unsigned int temp = right; 638 | right = left; 639 | left = temp; 640 | } 641 | String out; 642 | if (left >= len) 643 | return out; 644 | if (right > len) 645 | right = len; 646 | char temp = buffer[right]; // save the replaced character 647 | buffer[right] = '\0'; 648 | out = buffer + left; // pointer arithmetic 649 | buffer[right] = temp; //restore character 650 | return out; 651 | } 652 | 653 | /*********************************************/ 654 | /* Modification */ 655 | /*********************************************/ 656 | 657 | void String::replace(char find, char replace) 658 | { 659 | if (!buffer) 660 | return; 661 | for (char *p = buffer; *p; p++) 662 | { 663 | if (*p == find) 664 | *p = replace; 665 | } 666 | } 667 | 668 | void String::replace(const String &find, const String &replace) 669 | { 670 | if (len == 0 || find.len == 0) 671 | return; 672 | int diff = replace.len - find.len; 673 | char *readFrom = buffer; 674 | char *foundAt; 675 | if (diff == 0) 676 | { 677 | while ((foundAt = strstr(readFrom, find.buffer)) != NULL) 678 | { 679 | memcpy(foundAt, replace.buffer, replace.len); 680 | readFrom = foundAt + replace.len; 681 | } 682 | } 683 | else if (diff < 0) 684 | { 685 | char *writeTo = buffer; 686 | while ((foundAt = strstr(readFrom, find.buffer)) != NULL) 687 | { 688 | unsigned int n = foundAt - readFrom; 689 | memcpy(writeTo, readFrom, n); 690 | writeTo += n; 691 | memcpy(writeTo, replace.buffer, replace.len); 692 | writeTo += replace.len; 693 | readFrom = foundAt + find.len; 694 | len += diff; 695 | } 696 | strcpy(writeTo, readFrom); 697 | } 698 | else 699 | { 700 | unsigned int size = len; // compute size needed for result 701 | while ((foundAt = strstr(readFrom, find.buffer)) != NULL) 702 | { 703 | readFrom = foundAt + find.len; 704 | size += diff; 705 | } 706 | if (size == len) 707 | return; 708 | if (size > capacity && !changeBuffer(size)) 709 | return; // XXX: tell user! 710 | int index = len - 1; 711 | while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) 712 | { 713 | readFrom = buffer + index + find.len; 714 | memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); 715 | len += diff; 716 | buffer[len] = 0; 717 | memcpy(buffer + index, replace.buffer, replace.len); 718 | index--; 719 | } 720 | } 721 | } 722 | 723 | void String::remove(unsigned int index) 724 | { 725 | // Pass the biggest integer as the count. The remove method 726 | // below will take care of truncating it at the end of the 727 | // string. 728 | remove(index, (unsigned int)-1); 729 | } 730 | 731 | void String::remove(unsigned int index, unsigned int count) 732 | { 733 | if (index >= len) 734 | { 735 | return; 736 | } 737 | if (count <= 0) 738 | { 739 | return; 740 | } 741 | if (count > len - index) 742 | { 743 | count = len - index; 744 | } 745 | char *writeTo = buffer + index; 746 | len = len - count; 747 | strncpy(writeTo, buffer + index + count, len - index); 748 | buffer[len] = 0; 749 | } 750 | 751 | void String::toLowerCase(void) 752 | { 753 | if (!buffer) 754 | return; 755 | for (char *p = buffer; *p; p++) 756 | { 757 | *p = tolower(*p); 758 | } 759 | } 760 | 761 | void String::toUpperCase(void) 762 | { 763 | if (!buffer) 764 | return; 765 | for (char *p = buffer; *p; p++) 766 | { 767 | *p = toupper(*p); 768 | } 769 | } 770 | 771 | void String::trim(void) 772 | { 773 | if (!buffer || len == 0) 774 | return; 775 | char *begin = buffer; 776 | while (isspace(*begin)) 777 | begin++; 778 | char *end = buffer + len - 1; 779 | while (isspace(*end) && end >= begin) 780 | end--; 781 | len = end + 1 - begin; 782 | if (begin > buffer) 783 | memcpy(buffer, begin, len); 784 | buffer[len] = 0; 785 | } 786 | 787 | /*********************************************/ 788 | /* Parsing / Conversion */ 789 | /*********************************************/ 790 | 791 | long String::toInt(void) const 792 | { 793 | if (buffer) 794 | return atol(buffer); 795 | return 0; 796 | } 797 | 798 | float String::toFloat(void) const 799 | { 800 | return float(toDouble()); 801 | } 802 | 803 | double String::toDouble(void) const 804 | { 805 | if (buffer) 806 | return atof(buffer); 807 | return 0; 808 | } 809 | -------------------------------------------------------------------------------- /cores/wasm32/WString.h: -------------------------------------------------------------------------------- 1 | /* 2 | WString.h - String library for Wiring & Arduino 3 | ...mostly rewritten by Paul Stoffregen... 4 | Copyright (c) 2009-10 Hernando Barragan. All right reserved. 5 | Copyright 2011, Paul Stoffregen, paul@pjrc.com 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef String_class_h 23 | #define String_class_h 24 | #ifdef __cplusplus 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "Itoa.h" 31 | 32 | // An inherited class for holding the result of a concatenation. These 33 | // result objects are assumed to be writable by subsequent concatenations. 34 | class StringSumHelper; 35 | 36 | // The string class 37 | class String 38 | { 39 | // use a function pointer to allow for "if (s)" without the 40 | // complications of an operator bool(). for more information, see: 41 | // http://www.artima.com/cppsource/safebool.html 42 | typedef void (String::*StringIfHelperType)() const; 43 | void StringIfHelper() const {} 44 | 45 | public: 46 | // constructors 47 | // creates a copy of the initial value. 48 | // if the initial value is null or invalid, or if memory allocation 49 | // fails, the string will be marked as invalid (i.e. "if (s)" will 50 | // be false). 51 | String(const char *cstr = ""); 52 | String(const String &str); 53 | #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) 54 | String(String &&rval); 55 | String(StringSumHelper &&rval); 56 | #endif 57 | explicit String(char c); 58 | explicit String(unsigned char, unsigned char base=10); 59 | explicit String(int, unsigned char base=10); 60 | explicit String(unsigned int, unsigned char base=10); 61 | explicit String(long, unsigned char base=10); 62 | explicit String(unsigned long, unsigned char base=10); 63 | explicit String(float, unsigned char decimalPlaces=2); 64 | explicit String(double, unsigned char decimalPlaces=2); 65 | ~String(void); 66 | 67 | // memory management 68 | // return true on success, false on failure (in which case, the string 69 | // is left unchanged). reserve(0), if successful, will validate an 70 | // invalid string (i.e., "if (s)" will be true afterwards) 71 | unsigned char reserve(unsigned int size); 72 | inline unsigned int length(void) const {return len;} 73 | 74 | // creates a copy of the assigned value. if the value is null or 75 | // invalid, or if the memory allocation fails, the string will be 76 | // marked as invalid ("if (s)" will be false). 77 | String & operator = (const String &rhs); 78 | String & operator = (const char *cstr); 79 | #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) 80 | String & operator = (String &&rval); 81 | String & operator = (StringSumHelper &&rval); 82 | #endif 83 | 84 | // concatenate (works w/ built-in types) 85 | 86 | // returns true on success, false on failure (in which case, the string 87 | // is left unchanged). if the argument is null or invalid, the 88 | // concatenation is considered unsucessful. 89 | unsigned char concat(const String &str); 90 | unsigned char concat(const char *cstr); 91 | unsigned char concat(char c); 92 | unsigned char concat(unsigned char c); 93 | unsigned char concat(int num); 94 | unsigned char concat(unsigned int num); 95 | unsigned char concat(long num); 96 | unsigned char concat(unsigned long num); 97 | unsigned char concat(float num); 98 | unsigned char concat(double num); 99 | 100 | // if there's not enough memory for the concatenated value, the string 101 | // will be left unchanged (but this isn't signalled in any way) 102 | String & operator += (const String &rhs) {concat(rhs); return (*this);} 103 | String & operator += (const char *cstr) {concat(cstr); return (*this);} 104 | String & operator += (char c) {concat(c); return (*this);} 105 | String & operator += (unsigned char num) {concat(num); return (*this);} 106 | String & operator += (int num) {concat(num); return (*this);} 107 | String & operator += (unsigned int num) {concat(num); return (*this);} 108 | String & operator += (long num) {concat(num); return (*this);} 109 | String & operator += (unsigned long num) {concat(num); return (*this);} 110 | String & operator += (float num) {concat(num); return (*this);} 111 | String & operator += (double num) {concat(num); return (*this);} 112 | 113 | friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); 114 | friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); 115 | friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); 116 | friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num); 117 | friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); 118 | friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); 119 | friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); 120 | friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); 121 | friend StringSumHelper & operator + (const StringSumHelper &lhs, float num); 122 | friend StringSumHelper & operator + (const StringSumHelper &lhs, double num); 123 | 124 | // comparison (only works w/ Strings and "strings") 125 | operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } 126 | int compareTo(const String &s) const; 127 | unsigned char equals(const String &s) const; 128 | unsigned char equals(const char *cstr) const; 129 | unsigned char operator == (const String &rhs) const {return equals(rhs);} 130 | unsigned char operator == (const char *cstr) const {return equals(cstr);} 131 | unsigned char operator != (const String &rhs) const {return !equals(rhs);} 132 | unsigned char operator != (const char *cstr) const {return !equals(cstr);} 133 | unsigned char operator < (const String &rhs) const; 134 | unsigned char operator > (const String &rhs) const; 135 | unsigned char operator <= (const String &rhs) const; 136 | unsigned char operator >= (const String &rhs) const; 137 | unsigned char equalsIgnoreCase(const String &s) const; 138 | unsigned char startsWith( const String &prefix) const; 139 | unsigned char startsWith(const String &prefix, unsigned int offset) const; 140 | unsigned char endsWith(const String &suffix) const; 141 | 142 | // character acccess 143 | char charAt(unsigned int index) const; 144 | void setCharAt(unsigned int index, char c); 145 | char operator [] (unsigned int index) const; 146 | char& operator [] (unsigned int index); 147 | void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; 148 | void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const 149 | { getBytes((unsigned char *)buf, bufsize, index); } 150 | const char* c_str() const { return buffer; } 151 | char* begin() { return buffer; } 152 | char* end() { return buffer + length(); } 153 | const char* begin() const { return c_str(); } 154 | const char* end() const { return c_str() + length(); } 155 | 156 | // search 157 | int indexOf( char ch ) const; 158 | int indexOf( char ch, unsigned int fromIndex ) const; 159 | int indexOf( const String &str ) const; 160 | int indexOf( const String &str, unsigned int fromIndex ) const; 161 | int lastIndexOf( char ch ) const; 162 | int lastIndexOf( char ch, unsigned int fromIndex ) const; 163 | int lastIndexOf( const String &str ) const; 164 | int lastIndexOf( const String &str, unsigned int fromIndex ) const; 165 | String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); }; 166 | String substring( unsigned int beginIndex, unsigned int endIndex ) const; 167 | 168 | // modification 169 | void replace(char find, char replace); 170 | void replace(const String& find, const String& replace); 171 | void remove(unsigned int index); 172 | void remove(unsigned int index, unsigned int count); 173 | void toLowerCase(void); 174 | void toUpperCase(void); 175 | void trim(void); 176 | 177 | // parsing/conversion 178 | long toInt(void) const; 179 | float toFloat(void) const; 180 | double toDouble(void) const; 181 | 182 | protected: 183 | char *buffer; // the actual char array 184 | unsigned int capacity; // the array length minus one (for the '\0') 185 | unsigned int len; // the String length (not counting the '\0') 186 | protected: 187 | void init(void); 188 | void invalidate(void); 189 | unsigned char changeBuffer(unsigned int maxStrLen); 190 | unsigned char concat(const char *cstr, unsigned int length); 191 | 192 | // copy and move 193 | String & copy(const char *cstr, unsigned int length); 194 | #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) 195 | void move(String &rhs); 196 | #endif 197 | }; 198 | 199 | class StringSumHelper : public String 200 | { 201 | public: 202 | StringSumHelper(const String &s) : String(s) {} 203 | StringSumHelper(const char *p) : String(p) {} 204 | StringSumHelper(char c) : String(c) {} 205 | StringSumHelper(unsigned char num) : String(num) {} 206 | StringSumHelper(int num) : String(num) {} 207 | StringSumHelper(unsigned int num) : String(num) {} 208 | StringSumHelper(long num) : String(num) {} 209 | StringSumHelper(unsigned long num) : String(num) {} 210 | StringSumHelper(float num) : String(num) {} 211 | StringSumHelper(double num) : String(num) {} 212 | }; 213 | 214 | #endif // __cplusplus 215 | #endif // String_class_h 216 | -------------------------------------------------------------------------------- /cores/wasm32/Wasmino.cpp: -------------------------------------------------------------------------------- 1 | #include "Wasmino.h" 2 | 3 | #define _BSD_SOURCE 4 | #include 5 | #include 6 | 7 | extern "C" { 8 | 9 | #define DEFAULT_PIN_COUNT 16 10 | #define MAX_PIN_COUNT 256 11 | 12 | #define WASMINO_ATTR_INTERRUPT_ENABLED (1 << 0) 13 | #define WASMINO_ATTR_IN_INTERRUPT (1 << 1) 14 | 15 | #define WASMINO_PIN_ATTR_OUTPUT (1 << 0) 16 | #define WASMINO_PIN_ATTR_ANALOG (1 << 1) 17 | #define WASMINO_PIN_ATTR_INTERRUPT_RISING (1 << 2) 18 | #define WASMINO_PIN_ATTR_INTERRUPT_FALLING (1 << 3) 19 | 20 | unsigned long microseconds = 0; 21 | 22 | #define ASYNCIFY_BUFFER_SIZE 1024 23 | uint32_t asyncifyBuffer[1024] = { 0 }; 24 | 25 | struct wasminoPinState { 26 | unsigned long attr; 27 | float input; 28 | float output; 29 | void (*isr)(); 30 | }; 31 | 32 | struct wasminoState { 33 | unsigned long attr; 34 | unsigned long pinCount; 35 | struct wasminoPinState pinStates[MAX_PIN_COUNT]; 36 | struct timespec uptime; 37 | float interruptThreshold; 38 | }; 39 | 40 | struct wasminoState state = { 41 | .attr = WASMINO_ATTR_INTERRUPT_ENABLED, 42 | .pinCount = DEFAULT_PIN_COUNT, 43 | .pinStates = { 0 }, 44 | .uptime = { 0 }, 45 | .interruptThreshold = 0.5f, 46 | }; 47 | 48 | struct wasminoPinState *pinStates = state.pinStates; 49 | 50 | 51 | #ifdef WASMINO_EXT_NANOSLEEP 52 | extern void _nanosleep(unsigned long s, unsigned long ns) __attribute__((import_module("wasmino"), import_name("nanosleep"))); 53 | #else 54 | 55 | static void _nanosleep(unsigned long s, unsigned long ns) { 56 | struct timespec req = { 57 | .tv_sec = s, 58 | .tv_nsec = ns, 59 | }; 60 | struct timespec rem; 61 | do { 62 | rem = { 0 }; 63 | nanosleep(&req, &rem); 64 | req = rem; 65 | } while (req.tv_sec > 0 || req.tv_nsec > 0); 66 | } 67 | #endif 68 | 69 | static void wasminoNanosleep(unsigned long s, unsigned long ns) { 70 | if (state.attr & WASMINO_ATTR_IN_INTERRUPT) { 71 | // disable sleep during interrupt 72 | return; 73 | } 74 | struct timespec ts; 75 | ts = state.uptime; 76 | _nanosleep(s, ns); 77 | ts.tv_sec += s; 78 | ts.tv_nsec += ns; 79 | if (ts.tv_nsec > 1000000000) { 80 | ts.tv_nsec -= 1000000000; 81 | ts.tv_sec += 1; 82 | } 83 | state.uptime = ts; 84 | } 85 | 86 | unsigned long millis(void) { 87 | return state.uptime.tv_sec * 1000 + state.uptime.tv_nsec / 1000000; 88 | } 89 | 90 | unsigned long micros(void) { 91 | return state.uptime.tv_sec * 1000000 + state.uptime.tv_nsec / 1000; 92 | } 93 | 94 | void delay(unsigned long ms) { 95 | wasminoNanosleep(ms / 1000, (ms % 1000) * 1000000); 96 | } 97 | 98 | void delayMicroseconds(unsigned int us) { 99 | wasminoNanosleep(us / 1000000, (us % 1000000) * 1000); 100 | } 101 | 102 | void pinMode(uint8_t pin, uint8_t mode) { 103 | if (pin >= state.pinCount) { 104 | return; 105 | } 106 | struct wasminoPinState *ps = &pinStates[pin]; 107 | switch (mode) 108 | { 109 | case INPUT: 110 | ps->attr &= WASMINO_PIN_ATTR_OUTPUT; 111 | break; 112 | case INPUT_PULLUP: 113 | ps->attr &= WASMINO_PIN_ATTR_OUTPUT; 114 | ps->output = 1.f; 115 | break; 116 | case OUTPUT: 117 | ps->attr |= WASMINO_PIN_ATTR_OUTPUT; 118 | default: 119 | break; 120 | } 121 | } 122 | 123 | int digitalRead(uint8_t pin) 124 | { 125 | if (pin >= state.pinCount) { 126 | return LOW; 127 | } 128 | return pinStates[pin].input ? HIGH : LOW; 129 | } 130 | 131 | void digitalWrite(uint8_t pin, uint8_t val) 132 | { 133 | if (pin >= state.pinCount) { 134 | return; 135 | } 136 | pinStates[pin].attr &= WASMINO_PIN_ATTR_ANALOG; 137 | pinStates[pin].output = val ? 1.f : 0.f; 138 | } 139 | 140 | int analogRead(uint8_t pin) 141 | { 142 | if (pin >= state.pinCount) { 143 | return 0; 144 | } 145 | float value = pinStates[pin].input; 146 | return value * 255; 147 | } 148 | 149 | void analogReference(uint8_t mode) 150 | { 151 | // NOT IMPLEMENTED 152 | } 153 | 154 | void analogWrite(uint8_t pin, int val) 155 | { 156 | if (pin >= state.pinCount) { 157 | return; 158 | } 159 | if (val < 0) { 160 | val = 0; 161 | } else if (val > 255) { 162 | val = 255; 163 | } 164 | pinStates[pin].attr |= WASMINO_PIN_ATTR_ANALOG; 165 | pinStates[pin].output = val / 255.0f; 166 | } 167 | 168 | void attachInterrupt(uint8_t intr, void (*isr)(), int mode) { 169 | if (intr >= state.pinCount) { 170 | return; 171 | } 172 | pinStates[intr].attr &= WASMINO_PIN_ATTR_INTERRUPT_RISING; 173 | pinStates[intr].attr &= WASMINO_PIN_ATTR_INTERRUPT_FALLING; 174 | pinStates[intr].isr = isr; 175 | switch (mode) { 176 | case RISING: 177 | pinStates[intr].attr |= WASMINO_PIN_ATTR_INTERRUPT_RISING; 178 | break; 179 | case FALLING: 180 | pinStates[intr].attr |= WASMINO_PIN_ATTR_INTERRUPT_FALLING; 181 | break; 182 | case CHANGE: 183 | pinStates[intr].attr |= WASMINO_PIN_ATTR_INTERRUPT_RISING; 184 | pinStates[intr].attr |= WASMINO_PIN_ATTR_INTERRUPT_FALLING; 185 | break; 186 | default: 187 | break; 188 | } 189 | } 190 | 191 | void detachInterrupt(uint8_t intr) { 192 | if (intr >= state.pinCount) { 193 | return; 194 | } 195 | pinStates[intr].attr &= WASMINO_PIN_ATTR_INTERRUPT_RISING; 196 | pinStates[intr].attr &= WASMINO_PIN_ATTR_INTERRUPT_FALLING; 197 | } 198 | 199 | void interrupts() { 200 | state.attr |= WASMINO_ATTR_INTERRUPT_ENABLED; 201 | } 202 | 203 | void noInterrupts() { 204 | state.attr &= WASMINO_ATTR_INTERRUPT_ENABLED; 205 | } 206 | 207 | // Wasmino Extensions, client side 208 | void rawWrite(uint8_t pin, float value) 209 | { 210 | if (pin >= state.pinCount) { 211 | return; 212 | } 213 | pinStates[pin].output = value; 214 | } 215 | 216 | float rawRead(uint8_t pin) 217 | { 218 | if (pin >= state.pinCount) { 219 | return 0.0f; 220 | } 221 | return pinStates[pin].input; 222 | } 223 | 224 | void setPinCount(uint8_t count) 225 | { 226 | state.pinCount = count; 227 | } 228 | 229 | void interruptThreshold(float threshold) { 230 | state.interruptThreshold = threshold; 231 | } 232 | 233 | // Wasmino Extensions, host side 234 | uint8_t getPinMode(uint8_t pin) 235 | __attribute__((export_name("wasminoGetPinMode"))) 236 | { 237 | return pinStates[pin].attr & WASMINO_PIN_ATTR_OUTPUT ? OUTPUT : INPUT; 238 | } 239 | 240 | uint8_t getPinCount() 241 | __attribute__((export_name("wasminoGetPinCount"))) 242 | { 243 | return state.pinCount; 244 | } 245 | 246 | float wasminoReadPin(uint8_t pin) 247 | __attribute__((export_name("wasminoReadPin"))) 248 | { 249 | if (pin >= state.pinCount) { 250 | return 0.0f; 251 | } 252 | return pinStates[pin].output; 253 | } 254 | 255 | void wasminoWritePin(uint8_t pin, float value) 256 | __attribute__((export_name("wasminoWritePin"))) 257 | { 258 | if (pin >= state.pinCount) { 259 | return; 260 | } 261 | struct wasminoPinState *ps = &pinStates[pin]; 262 | float orig = ps->input; 263 | ps->input = value; 264 | if (!(state.attr & WASMINO_ATTR_INTERRUPT_ENABLED)) { 265 | return; 266 | } 267 | if ( 268 | ( 269 | (ps->attr & WASMINO_PIN_ATTR_INTERRUPT_RISING) && 270 | (orig < state.interruptThreshold) && 271 | (value >= state.interruptThreshold) 272 | ) || 273 | ( 274 | (ps->attr & WASMINO_PIN_ATTR_INTERRUPT_FALLING) && 275 | (orig > state.interruptThreshold) && 276 | (value <= state.interruptThreshold) 277 | ) 278 | ) { 279 | ps->attr |= WASMINO_ATTR_IN_INTERRUPT; 280 | pinStates[pin].isr(); 281 | ps->attr &= WASMINO_ATTR_IN_INTERRUPT; 282 | } 283 | } 284 | 285 | void wasminoSetUptime(unsigned long s, unsigned long ns) 286 | __attribute__((export_name("wasminoSetUptime"))) 287 | { 288 | state.uptime.tv_sec = s; 289 | state.uptime.tv_nsec = ns; 290 | } 291 | 292 | void *_wasminoMalloc(size_t size) 293 | __attribute__((export_name("malloc"))) 294 | { 295 | return malloc(size); 296 | } 297 | 298 | void _wasminoFree(void *ptr) 299 | __attribute__((export_name("free"))) 300 | { 301 | free(ptr); 302 | } 303 | 304 | // main func 305 | int main(int argc, const char *argv[]) 306 | { 307 | int iter = -1; 308 | if (argc >= 2) { 309 | iter = atoi(argv[1]); 310 | } 311 | delay(0); 312 | setup(); 313 | delay(0); 314 | while (iter != 0) { 315 | loop(); 316 | delay(0); 317 | if (iter > 0) { 318 | iter--; 319 | } 320 | } 321 | } 322 | 323 | } 324 | -------------------------------------------------------------------------------- /cores/wasm32/Wasmino.h: -------------------------------------------------------------------------------- 1 | #ifndef Wasmino_h 2 | #define Wasmino_h 3 | 4 | #include "Arduino.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | // Wasmino Extensions 11 | void rawWrite(uint8_t pin, float value); 12 | float rawRead(uint8_t pin); 13 | 14 | void setPinCount(uint8_t count); 15 | inline static void pinCount(uint8_t count) { 16 | setPinCount(count); 17 | } 18 | 19 | void interruptThreshold(float threshold); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /cores/wasm32/binary.h: -------------------------------------------------------------------------------- 1 | /* 2 | binary.h - Definitions for binary constants 3 | Copyright (c) 2006 David A. Mellis. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef Binary_h 21 | #define Binary_h 22 | 23 | #define B0 0 24 | #define B00 0 25 | #define B000 0 26 | #define B0000 0 27 | #define B00000 0 28 | #define B000000 0 29 | #define B0000000 0 30 | #define B00000000 0 31 | #define B1 1 32 | #define B01 1 33 | #define B001 1 34 | #define B0001 1 35 | #define B00001 1 36 | #define B000001 1 37 | #define B0000001 1 38 | #define B00000001 1 39 | #define B10 2 40 | #define B010 2 41 | #define B0010 2 42 | #define B00010 2 43 | #define B000010 2 44 | #define B0000010 2 45 | #define B00000010 2 46 | #define B11 3 47 | #define B011 3 48 | #define B0011 3 49 | #define B00011 3 50 | #define B000011 3 51 | #define B0000011 3 52 | #define B00000011 3 53 | #define B100 4 54 | #define B0100 4 55 | #define B00100 4 56 | #define B000100 4 57 | #define B0000100 4 58 | #define B00000100 4 59 | #define B101 5 60 | #define B0101 5 61 | #define B00101 5 62 | #define B000101 5 63 | #define B0000101 5 64 | #define B00000101 5 65 | #define B110 6 66 | #define B0110 6 67 | #define B00110 6 68 | #define B000110 6 69 | #define B0000110 6 70 | #define B00000110 6 71 | #define B111 7 72 | #define B0111 7 73 | #define B00111 7 74 | #define B000111 7 75 | #define B0000111 7 76 | #define B00000111 7 77 | #define B1000 8 78 | #define B01000 8 79 | #define B001000 8 80 | #define B0001000 8 81 | #define B00001000 8 82 | #define B1001 9 83 | #define B01001 9 84 | #define B001001 9 85 | #define B0001001 9 86 | #define B00001001 9 87 | #define B1010 10 88 | #define B01010 10 89 | #define B001010 10 90 | #define B0001010 10 91 | #define B00001010 10 92 | #define B1011 11 93 | #define B01011 11 94 | #define B001011 11 95 | #define B0001011 11 96 | #define B00001011 11 97 | #define B1100 12 98 | #define B01100 12 99 | #define B001100 12 100 | #define B0001100 12 101 | #define B00001100 12 102 | #define B1101 13 103 | #define B01101 13 104 | #define B001101 13 105 | #define B0001101 13 106 | #define B00001101 13 107 | #define B1110 14 108 | #define B01110 14 109 | #define B001110 14 110 | #define B0001110 14 111 | #define B00001110 14 112 | #define B1111 15 113 | #define B01111 15 114 | #define B001111 15 115 | #define B0001111 15 116 | #define B00001111 15 117 | #define B10000 16 118 | #define B010000 16 119 | #define B0010000 16 120 | #define B00010000 16 121 | #define B10001 17 122 | #define B010001 17 123 | #define B0010001 17 124 | #define B00010001 17 125 | #define B10010 18 126 | #define B010010 18 127 | #define B0010010 18 128 | #define B00010010 18 129 | #define B10011 19 130 | #define B010011 19 131 | #define B0010011 19 132 | #define B00010011 19 133 | #define B10100 20 134 | #define B010100 20 135 | #define B0010100 20 136 | #define B00010100 20 137 | #define B10101 21 138 | #define B010101 21 139 | #define B0010101 21 140 | #define B00010101 21 141 | #define B10110 22 142 | #define B010110 22 143 | #define B0010110 22 144 | #define B00010110 22 145 | #define B10111 23 146 | #define B010111 23 147 | #define B0010111 23 148 | #define B00010111 23 149 | #define B11000 24 150 | #define B011000 24 151 | #define B0011000 24 152 | #define B00011000 24 153 | #define B11001 25 154 | #define B011001 25 155 | #define B0011001 25 156 | #define B00011001 25 157 | #define B11010 26 158 | #define B011010 26 159 | #define B0011010 26 160 | #define B00011010 26 161 | #define B11011 27 162 | #define B011011 27 163 | #define B0011011 27 164 | #define B00011011 27 165 | #define B11100 28 166 | #define B011100 28 167 | #define B0011100 28 168 | #define B00011100 28 169 | #define B11101 29 170 | #define B011101 29 171 | #define B0011101 29 172 | #define B00011101 29 173 | #define B11110 30 174 | #define B011110 30 175 | #define B0011110 30 176 | #define B00011110 30 177 | #define B11111 31 178 | #define B011111 31 179 | #define B0011111 31 180 | #define B00011111 31 181 | #define B100000 32 182 | #define B0100000 32 183 | #define B00100000 32 184 | #define B100001 33 185 | #define B0100001 33 186 | #define B00100001 33 187 | #define B100010 34 188 | #define B0100010 34 189 | #define B00100010 34 190 | #define B100011 35 191 | #define B0100011 35 192 | #define B00100011 35 193 | #define B100100 36 194 | #define B0100100 36 195 | #define B00100100 36 196 | #define B100101 37 197 | #define B0100101 37 198 | #define B00100101 37 199 | #define B100110 38 200 | #define B0100110 38 201 | #define B00100110 38 202 | #define B100111 39 203 | #define B0100111 39 204 | #define B00100111 39 205 | #define B101000 40 206 | #define B0101000 40 207 | #define B00101000 40 208 | #define B101001 41 209 | #define B0101001 41 210 | #define B00101001 41 211 | #define B101010 42 212 | #define B0101010 42 213 | #define B00101010 42 214 | #define B101011 43 215 | #define B0101011 43 216 | #define B00101011 43 217 | #define B101100 44 218 | #define B0101100 44 219 | #define B00101100 44 220 | #define B101101 45 221 | #define B0101101 45 222 | #define B00101101 45 223 | #define B101110 46 224 | #define B0101110 46 225 | #define B00101110 46 226 | #define B101111 47 227 | #define B0101111 47 228 | #define B00101111 47 229 | #define B110000 48 230 | #define B0110000 48 231 | #define B00110000 48 232 | #define B110001 49 233 | #define B0110001 49 234 | #define B00110001 49 235 | #define B110010 50 236 | #define B0110010 50 237 | #define B00110010 50 238 | #define B110011 51 239 | #define B0110011 51 240 | #define B00110011 51 241 | #define B110100 52 242 | #define B0110100 52 243 | #define B00110100 52 244 | #define B110101 53 245 | #define B0110101 53 246 | #define B00110101 53 247 | #define B110110 54 248 | #define B0110110 54 249 | #define B00110110 54 250 | #define B110111 55 251 | #define B0110111 55 252 | #define B00110111 55 253 | #define B111000 56 254 | #define B0111000 56 255 | #define B00111000 56 256 | #define B111001 57 257 | #define B0111001 57 258 | #define B00111001 57 259 | #define B111010 58 260 | #define B0111010 58 261 | #define B00111010 58 262 | #define B111011 59 263 | #define B0111011 59 264 | #define B00111011 59 265 | #define B111100 60 266 | #define B0111100 60 267 | #define B00111100 60 268 | #define B111101 61 269 | #define B0111101 61 270 | #define B00111101 61 271 | #define B111110 62 272 | #define B0111110 62 273 | #define B00111110 62 274 | #define B111111 63 275 | #define B0111111 63 276 | #define B00111111 63 277 | #define B1000000 64 278 | #define B01000000 64 279 | #define B1000001 65 280 | #define B01000001 65 281 | #define B1000010 66 282 | #define B01000010 66 283 | #define B1000011 67 284 | #define B01000011 67 285 | #define B1000100 68 286 | #define B01000100 68 287 | #define B1000101 69 288 | #define B01000101 69 289 | #define B1000110 70 290 | #define B01000110 70 291 | #define B1000111 71 292 | #define B01000111 71 293 | #define B1001000 72 294 | #define B01001000 72 295 | #define B1001001 73 296 | #define B01001001 73 297 | #define B1001010 74 298 | #define B01001010 74 299 | #define B1001011 75 300 | #define B01001011 75 301 | #define B1001100 76 302 | #define B01001100 76 303 | #define B1001101 77 304 | #define B01001101 77 305 | #define B1001110 78 306 | #define B01001110 78 307 | #define B1001111 79 308 | #define B01001111 79 309 | #define B1010000 80 310 | #define B01010000 80 311 | #define B1010001 81 312 | #define B01010001 81 313 | #define B1010010 82 314 | #define B01010010 82 315 | #define B1010011 83 316 | #define B01010011 83 317 | #define B1010100 84 318 | #define B01010100 84 319 | #define B1010101 85 320 | #define B01010101 85 321 | #define B1010110 86 322 | #define B01010110 86 323 | #define B1010111 87 324 | #define B01010111 87 325 | #define B1011000 88 326 | #define B01011000 88 327 | #define B1011001 89 328 | #define B01011001 89 329 | #define B1011010 90 330 | #define B01011010 90 331 | #define B1011011 91 332 | #define B01011011 91 333 | #define B1011100 92 334 | #define B01011100 92 335 | #define B1011101 93 336 | #define B01011101 93 337 | #define B1011110 94 338 | #define B01011110 94 339 | #define B1011111 95 340 | #define B01011111 95 341 | #define B1100000 96 342 | #define B01100000 96 343 | #define B1100001 97 344 | #define B01100001 97 345 | #define B1100010 98 346 | #define B01100010 98 347 | #define B1100011 99 348 | #define B01100011 99 349 | #define B1100100 100 350 | #define B01100100 100 351 | #define B1100101 101 352 | #define B01100101 101 353 | #define B1100110 102 354 | #define B01100110 102 355 | #define B1100111 103 356 | #define B01100111 103 357 | #define B1101000 104 358 | #define B01101000 104 359 | #define B1101001 105 360 | #define B01101001 105 361 | #define B1101010 106 362 | #define B01101010 106 363 | #define B1101011 107 364 | #define B01101011 107 365 | #define B1101100 108 366 | #define B01101100 108 367 | #define B1101101 109 368 | #define B01101101 109 369 | #define B1101110 110 370 | #define B01101110 110 371 | #define B1101111 111 372 | #define B01101111 111 373 | #define B1110000 112 374 | #define B01110000 112 375 | #define B1110001 113 376 | #define B01110001 113 377 | #define B1110010 114 378 | #define B01110010 114 379 | #define B1110011 115 380 | #define B01110011 115 381 | #define B1110100 116 382 | #define B01110100 116 383 | #define B1110101 117 384 | #define B01110101 117 385 | #define B1110110 118 386 | #define B01110110 118 387 | #define B1110111 119 388 | #define B01110111 119 389 | #define B1111000 120 390 | #define B01111000 120 391 | #define B1111001 121 392 | #define B01111001 121 393 | #define B1111010 122 394 | #define B01111010 122 395 | #define B1111011 123 396 | #define B01111011 123 397 | #define B1111100 124 398 | #define B01111100 124 399 | #define B1111101 125 400 | #define B01111101 125 401 | #define B1111110 126 402 | #define B01111110 126 403 | #define B1111111 127 404 | #define B01111111 127 405 | #define B10000000 128 406 | #define B10000001 129 407 | #define B10000010 130 408 | #define B10000011 131 409 | #define B10000100 132 410 | #define B10000101 133 411 | #define B10000110 134 412 | #define B10000111 135 413 | #define B10001000 136 414 | #define B10001001 137 415 | #define B10001010 138 416 | #define B10001011 139 417 | #define B10001100 140 418 | #define B10001101 141 419 | #define B10001110 142 420 | #define B10001111 143 421 | #define B10010000 144 422 | #define B10010001 145 423 | #define B10010010 146 424 | #define B10010011 147 425 | #define B10010100 148 426 | #define B10010101 149 427 | #define B10010110 150 428 | #define B10010111 151 429 | #define B10011000 152 430 | #define B10011001 153 431 | #define B10011010 154 432 | #define B10011011 155 433 | #define B10011100 156 434 | #define B10011101 157 435 | #define B10011110 158 436 | #define B10011111 159 437 | #define B10100000 160 438 | #define B10100001 161 439 | #define B10100010 162 440 | #define B10100011 163 441 | #define B10100100 164 442 | #define B10100101 165 443 | #define B10100110 166 444 | #define B10100111 167 445 | #define B10101000 168 446 | #define B10101001 169 447 | #define B10101010 170 448 | #define B10101011 171 449 | #define B10101100 172 450 | #define B10101101 173 451 | #define B10101110 174 452 | #define B10101111 175 453 | #define B10110000 176 454 | #define B10110001 177 455 | #define B10110010 178 456 | #define B10110011 179 457 | #define B10110100 180 458 | #define B10110101 181 459 | #define B10110110 182 460 | #define B10110111 183 461 | #define B10111000 184 462 | #define B10111001 185 463 | #define B10111010 186 464 | #define B10111011 187 465 | #define B10111100 188 466 | #define B10111101 189 467 | #define B10111110 190 468 | #define B10111111 191 469 | #define B11000000 192 470 | #define B11000001 193 471 | #define B11000010 194 472 | #define B11000011 195 473 | #define B11000100 196 474 | #define B11000101 197 475 | #define B11000110 198 476 | #define B11000111 199 477 | #define B11001000 200 478 | #define B11001001 201 479 | #define B11001010 202 480 | #define B11001011 203 481 | #define B11001100 204 482 | #define B11001101 205 483 | #define B11001110 206 484 | #define B11001111 207 485 | #define B11010000 208 486 | #define B11010001 209 487 | #define B11010010 210 488 | #define B11010011 211 489 | #define B11010100 212 490 | #define B11010101 213 491 | #define B11010110 214 492 | #define B11010111 215 493 | #define B11011000 216 494 | #define B11011001 217 495 | #define B11011010 218 496 | #define B11011011 219 497 | #define B11011100 220 498 | #define B11011101 221 499 | #define B11011110 222 500 | #define B11011111 223 501 | #define B11100000 224 502 | #define B11100001 225 503 | #define B11100010 226 504 | #define B11100011 227 505 | #define B11100100 228 506 | #define B11100101 229 507 | #define B11100110 230 508 | #define B11100111 231 509 | #define B11101000 232 510 | #define B11101001 233 511 | #define B11101010 234 512 | #define B11101011 235 513 | #define B11101100 236 514 | #define B11101101 237 515 | #define B11101110 238 516 | #define B11101111 239 517 | #define B11110000 240 518 | #define B11110001 241 519 | #define B11110010 242 520 | #define B11110011 243 521 | #define B11110100 244 522 | #define B11110101 245 523 | #define B11110110 246 524 | #define B11110111 247 525 | #define B11111000 248 526 | #define B11111001 249 527 | #define B11111010 250 528 | #define B11111011 251 529 | #define B11111100 252 530 | #define B11111101 253 531 | #define B11111110 254 532 | #define B11111111 255 533 | 534 | #endif 535 | -------------------------------------------------------------------------------- /package.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import glob 3 | import io 4 | import itertools 5 | import json 6 | import os 7 | import zipfile 8 | 9 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 10 | 11 | EXCLUDED = [ 12 | "*.json", 13 | "requirements.txt", 14 | "**.zip", 15 | "**.py" 16 | ] 17 | 18 | def get_package_info(): 19 | package_name = None 20 | package_version = None 21 | package_description = None 22 | boards = [] 23 | with open("platform.txt") as f: 24 | for line in f.readlines(): 25 | splits = line.strip().split("=", 2) 26 | key = splits[0] 27 | value = splits[-1] 28 | if key == "package": 29 | package_name = value 30 | elif key == "version": 31 | package_version = value 32 | elif key == "name": 33 | package_description = value 34 | with open("boards.txt") as f: 35 | for line in f.readlines(): 36 | splits = line.strip().split("=", 2) 37 | key = splits[0] 38 | value = splits[-1] 39 | if key.endswith(".name"): 40 | boards.append(value) 41 | if package_name is None: 42 | raise RuntimeError("Cannot get name of package (package=... in platform.txt)") 43 | if package_version is None: 44 | raise RuntimeError("Cannot get version of package (version=... in platform.txt)") 45 | if package_description is None: 46 | raise RuntimeError("Cannot get description of package (name=... in platform.txt)") 47 | if len(boards) == 0: 48 | raise RuntimeError("No boards found") 49 | return { 50 | "name": package_name, 51 | "version": package_version, 52 | "description": package_description, 53 | "boards": boards 54 | } 55 | 56 | def gen_package_index(out_file, package_url): 57 | with open("package_index_template.json") as f: 58 | template = json.load(f) 59 | pkg_info = get_package_info() 60 | platform = template["packages"][0]["platforms"][0] 61 | platform["name"] = pkg_info["description"] 62 | platform["version"] = pkg_info["version"] 63 | platform["url"] = package_url 64 | platform["archiveFileName"] = package_url.split("/")[-1] 65 | platform["boards"] = [{"name": b} for b in pkg_info["boards"]] 66 | json.dump(template, out_file) 67 | 68 | 69 | def gen_package(out_file): 70 | pkg_info = get_package_info() 71 | all_files = glob.glob("**", recursive=True) 72 | excluded_files = list(itertools.chain(*[glob.glob(exclude, recursive=True) for exclude in EXCLUDED])) 73 | included_files = [f for f in all_files if f not in excluded_files] 74 | with zipfile.ZipFile(out_file, "x") as z: 75 | for filename in included_files: 76 | z.write(filename, os.path.join(f"{pkg_info['name']}-{pkg_info['version']}", filename)) 77 | 78 | 79 | def serve(port: int, package_name: str): 80 | import bottle 81 | 82 | b = bottle.Bottle() 83 | package_path = f"/{package_name}.zip" 84 | 85 | @b.route("/") 86 | def index(): 87 | return "Development Server" 88 | 89 | @b.route(f"/package_{package_name}_index.json") 90 | def package_index(): 91 | package_url = "/".join(bottle.request.url.split("/")[:-1]) + package_path 92 | out_file = io.StringIO() 93 | gen_package_index(out_file, package_url) 94 | bottle.response.content_type = "application/json" 95 | return out_file.getvalue() 96 | 97 | @b.route(package_path) 98 | def package(): 99 | out_file = io.BytesIO() 100 | gen_package(out_file) 101 | bottle.response.content_type = "application/zip" 102 | return out_file.getvalue() 103 | 104 | b.run(port=port) 105 | 106 | 107 | def main(): 108 | parser = argparse.ArgumentParser() 109 | 110 | pkg_info = get_package_info() 111 | 112 | parser.add_argument("--serve", action="store_true") 113 | parser.add_argument("--port", type=int, default=58080) 114 | parser.add_argument("--index", default=f"package_{pkg_info['name']}_index.json") 115 | parser.add_argument("--package", default=f"package_{pkg_info['name']}_{pkg_info['version']}.zip") 116 | parser.add_argument("--package-url", type=str) 117 | 118 | args = parser.parse_args() 119 | if args.serve: 120 | serve(args.port, pkg_info['name']) 121 | else: 122 | if args.package_url is None: 123 | raise RuntimeError("Need to specify --package-url") 124 | with open(args.index, "w") as f: 125 | gen_package_index(f, args.package_url) 126 | with open(args.package, "wb") as f: 127 | gen_package(f) 128 | 129 | 130 | if __name__ == "__main__": 131 | main() 132 | -------------------------------------------------------------------------------- /package_index_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | { 4 | "name": "wasmino", 5 | "maintainer": "Wasmino", 6 | "websiteURL": "https://github.com/wasmino", 7 | "email": "support@example.com", 8 | "help": { 9 | "online": "https://github.com/wasmino" 10 | }, 11 | "platforms": [ 12 | { 13 | "name": "Wasmino Virtual Boards", 14 | "architecture": "wasm32", 15 | "version": "", 16 | "category": "wasm32", 17 | "url": "", 18 | "archiveFileName": "", 19 | "help": { 20 | "online": "https://github.com/wasmino" 21 | }, 22 | "boards": [], 23 | "toolsDependencies": [ 24 | { 25 | "packager": "wasmino", 26 | "name": "wasi-sdk", 27 | "version": "12.0" 28 | }, 29 | { 30 | "packager": "wasmino", 31 | "name": "gist", 32 | "version": "0.0.4" 33 | }, 34 | { 35 | "packager": "wasmino", 36 | "name": "binaryen", 37 | "version": "97" 38 | } 39 | ] 40 | } 41 | ], 42 | "tools": [ 43 | { 44 | "name": "wasi-sdk", 45 | "version": "12.0", 46 | "systems": [ 47 | { 48 | "host": "i686-mingw32", 49 | "url": "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-mingw.tar.gz", 50 | "archiveFileName": "wasi-sdk-12.0-mingw.tar.gz", 51 | "checksum": "SHA-256:ac6a96bab41eb1979eda2fa35e1d6d701588feb4131a76497928fb90769d76e0", 52 | "size": "141815922" 53 | }, 54 | { 55 | "host": "x86_64-linux-gnu", 56 | "url": "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz", 57 | "archiveFileName": "wasi-sdk-12.0-linux.tar.gz", 58 | "checksum": "SHA-256:fa47694d75bf6fce98fbe7927193298b25ee03dade27fca453d7dd530378973a", 59 | "size": "49511675" 60 | }, 61 | { 62 | "host": "x86_64-apple-darwin", 63 | "url": "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz", 64 | "archiveFileName": "wasi-sdk-12.0-macos.tar.gz", 65 | "checksum": "SHA-256:8ee25f9c3fde618feea5c57adad385152626784b6b6b52fb563e5ed832bf53ef", 66 | "size": "45090499" 67 | } 68 | ] 69 | }, 70 | { 71 | "name": "gist", 72 | "version": "0.0.4", 73 | "systems": [ 74 | { 75 | "host":"i686-mingw32", 76 | "url": "https://github.com/gyf304/go-gist/releases/download/v0.0.4/gist-windows-386.zip", 77 | "archiveFileName": "gist-windows-386.zip", 78 | "checksum": "SHA-256:25bf388a25e11da0b1b9c6dfa374dcdf0ddccf3905afebe4a154f34d30304558", 79 | "size": "4413702" 80 | }, 81 | { 82 | "host": "x86_64-linux-gnu", 83 | "url": "https://github.com/gyf304/go-gist/releases/download/v0.0.4/gist-linux-amd64.tar.gz", 84 | "archiveFileName": "gist-linux-amd64.tar.gz", 85 | "checksum": "SHA-256:770c2a827f0cca11b6345dc0c00e8b5ab24db8a2bf616a5a6f578253dc31024a", 86 | "size": "4654660" 87 | }, 88 | { 89 | "host": "x86_64-apple-darwin", 90 | "url": "https://github.com/gyf304/go-gist/releases/download/v0.0.4/gist-darwin-amd64.tar.gz", 91 | "archiveFileName": "gist-darwin-amd64.tar.gz", 92 | "checksum": "SHA-256:bb8366250a8ab37a6501378bb87bbe2cec1d80866627f2b19d1d4e203f972496", 93 | "size": "4559367" 94 | } 95 | ] 96 | }, 97 | { 98 | "name": "binaryen", 99 | "version": "97", 100 | "systems": [ 101 | { 102 | "host":"i686-mingw32", 103 | "url": "https://github.com/WebAssembly/binaryen/releases/download/version_97/binaryen-version_97-x86_64-windows.tar.gz", 104 | "archiveFileName": "binaryen-version_97-x86_64-windows.tar.gz", 105 | "checksum": "SHA-256:0c2dcba2ac3d834e5f09f2be83cbe693b71bde3f3d2b5eee1b10281daaacdeb8", 106 | "size": "27130776" 107 | }, 108 | { 109 | "host": "x86_64-linux-gnu", 110 | "url": "https://github.com/WebAssembly/binaryen/releases/download/version_97/binaryen-version_97-x86_64-linux.tar.gz", 111 | "archiveFileName": "binaryen-version_97-x86_64-linux.tar.gz", 112 | "checksum": "SHA-256:7eb18a35a6c91d49da42b775293c14945eecc2ea125dafbd4fba83cdf326e8e6", 113 | "size": "31756118" 114 | }, 115 | { 116 | "host": "x86_64-apple-darwin", 117 | "url": "https://github.com/WebAssembly/binaryen/releases/download/version_97/binaryen-version_97-x86_64-macos.tar.gz", 118 | "archiveFileName": "binaryen-version_97-x86_64-macos.tar.gz", 119 | "checksum": "SHA-256:e34f3265d5d6b5fb3e76eaaa5f7304d51365a525ddf2c9671228cc1675906e99", 120 | "size": "3767730" 121 | } 122 | ] 123 | } 124 | ] 125 | } 126 | ] 127 | } 128 | -------------------------------------------------------------------------------- /platform.txt: -------------------------------------------------------------------------------- 1 | # Arduino AVR Core and platform. 2 | # ------------------------------ 3 | 4 | # For more info: 5 | # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification 6 | 7 | package=wasmino 8 | 9 | name=Wasmino Virtual Boards 10 | version=0.0.1 11 | 12 | # compile variables 13 | # --------------------- 14 | 15 | # Default "compiler.path" is correct, change only if you want to overidde the initial value 16 | compiler.path={runtime.tools.wasi-sdk.path}/bin/ 17 | 18 | compiler.c.cmd=clang 19 | compiler.c.flags=-x c -c -Os --target=wasm32 --sysroot={runtime.tools.wasi-sdk.path}/share/wasi-sysroot 20 | 21 | compiler.cpp.cmd=clang++ 22 | compiler.cpp.flags=-c -Os --target=wasm32 --sysroot={runtime.tools.wasi-sdk.path}/share/wasi-sysroot 23 | 24 | compiler.ar.cmd=ar 25 | compiler.ar.flags=rcs 26 | 27 | compiler.ld.cmd=wasm-ld 28 | compiler.ld.flags=-m wasm32 -L{runtime.tools.wasi-sdk.path}/share/wasi-sysroot/lib/wasm32-wasi 29 | #--allow-undefined-file= 30 | 31 | compiler.echo.cmd=echo 32 | compiler.echo.cmd.windows=cmd /c echo 33 | 34 | compiler.size.cmd=size 35 | # this can be overriden in boards.txt 36 | build.extra_flags= 37 | 38 | # AVR compile patterns 39 | # -------------------- 40 | 41 | ## Compile c files 42 | recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} {build.compiler.c.flags} -D__wasi__ -DARDUINO={runtime.ide.version} -DF_CPU={build.f_cpu} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" 43 | 44 | ## Compile c++ files 45 | recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {build.compiler.cpp.flags} -D__wasi__ -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" 46 | 47 | ## Compile S files 48 | recipe.S.o.pattern={compiler.echo.cmd} "cannot compile .S file" 49 | 50 | ## Create archives 51 | recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} "{archive_file_path}" "{object_file}" 52 | 53 | ## Combine gc-sections, archives, and objects 54 | recipe.c.combine.pattern="{compiler.path}{compiler.ld.cmd}" {compiler.ld.flags} {build.compiler.ld.flags} "-L{build.path}" {runtime.tools.wasi-sdk.path}/share/wasi-sysroot/lib/wasm32-wasi/crt1.o "{archive_file_path}" {object_files} -lm -lc -lc++ -lc++abi {runtime.tools.wasi-sdk.path}/lib/clang/11.0.0/lib/wasi/libclang_rt.builtins-wasm32.a -o "{build.path}/{build.project_name}.raw.wasm" 55 | 56 | ## Create Optimized wasm 57 | recipe.objcopy.wasm.pattern={runtime.tools.binaryen.path}/bin/wasm-opt -Os {build.compiler.binaryen_wasm_opt.flags} "{build.path}/{build.project_name}.raw.wasm" -o "{build.path}/{build.project_name}.wasm" 58 | 59 | ## Compute size 60 | recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.wasm" 61 | recipe.size.regex=^(?:DATA|Total)\s+([0-9]+).* 62 | recipe.size.regex.data=^(?:Total)\s+([0-9]+).* 63 | recipe.size.regex.eeprom=^(?:Total)\s+([0-9]+).* 64 | 65 | ## Save hex 66 | recipe.output.tmp_file={build.project_name}.wasm 67 | recipe.output.save_file={build.project_name}.{build.variant}.wasm 68 | 69 | # USB Default Flags 70 | # Default blank usb manufacturer will be filled it at compile time 71 | # - from numeric vendor ID, set to Unknown otherwise 72 | build.usb_manufacturer= 73 | build.usb_flags= 74 | 75 | tools.gist.cmd.path={runtime.tools.gist.path}/gist 76 | tools.gist.upload.params.verbose= 77 | tools.gist.upload.params.quiet= 78 | tools.gist.upload.pattern="{cmd.path}" -t 60 --base64 -f {build.project_name}.{build.variant}.wasm.b64 "{build.path}/{build.project_name}.wasm" "--format=https://demo.wasmino.org/#src=gist://{{.ID}}" 79 | -------------------------------------------------------------------------------- /programmers.txt: -------------------------------------------------------------------------------- 1 | gist.name=GitHub Gist 2 | gist.communication=http 3 | gist.protocol=gist 4 | gist.program.tool={runtime.tools.gist.path}/gist 5 | gist.program.extra_params=-t 60 --base64 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | bottle==0.12.19 2 | --------------------------------------------------------------------------------