├── .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 | 
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 | 
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 | 
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 |
--------------------------------------------------------------------------------