Compare commits

...

71 Commits

Author SHA1 Message Date
4e99cd3ef1 0.0.26 2017-10-27 19:23:01 +01:00
57647318c4 Sensor fixes 2017-10-27 19:18:56 +01:00
2720698864 Fix infinite loop 2017-10-27 19:18:47 +01:00
c0bab4877a Merge branch 'master' of github.com:Microsoft/pxt-ev3 2017-10-27 15:17:24 +01:00
d2a1d10ada Add converter from RGF to PNG 2017-10-27 15:17:21 +01:00
bcb68d937d Merge branch 'master' of https://github.com/microsoft/pxt-ev3 2017-10-27 02:52:47 -07:00
05a8395028 stop all motors 2017-10-27 02:52:42 -07:00
3a1601a419 Add rsf2wav.js 2017-10-27 10:42:33 +01:00
712c2178d2 simplify motor API 2017-10-27 01:47:25 -07:00
12cdad72c8 added puppet 2017-10-27 00:13:51 -07:00
95076f8f24 differentiate large/medium motors 2017-10-27 00:09:00 -07:00
6391620373 added 2 more activities 2017-10-26 23:58:34 -07:00
86212e2153 added sound of color 2017-10-26 23:46:55 -07:00
98e430f3c1 added example of converted lesson 2017-10-26 22:19:16 -07:00
5c7e856e7b removed incorrect buy link 2017-10-26 21:57:48 -07:00
a47988913e 0.0.25 2017-10-26 21:27:51 -07:00
ea72dba6c7 Merge pull request #17 from Microsoft/irevents
Ultrasonic + IR events + Remote events
2017-10-27 06:25:02 +02:00
215e846a54 refactored remote button 2017-10-26 21:10:37 -07:00
21b34cb459 simplified events 2017-10-26 20:57:18 -07:00
282134f5dc refactoring IR 2017-10-26 20:51:13 -07:00
6b44352839 event for ultrasonic module 2017-10-26 20:38:17 -07:00
9a883d5672 Merge branch 'master' into irevents 2017-10-26 20:21:06 -07:00
59ce4338d3 renaming IR events 2017-10-26 20:20:24 -07:00
90560050b8 Merge pull request #16 from Microsoft/fonts
Mounting events on various sensors
2017-10-27 05:19:36 +02:00
2c72173bfe Use the _query() infrastructure for polling 2017-10-25 13:34:05 +02:00
1a5992408b added event for color changes 2017-10-24 23:10:27 -07:00
0e1a3b7e6b adding setpixel 2017-10-24 22:05:24 -07:00
ea6bfa03bd touched -> pressed 2017-10-24 21:55:37 -07:00
20d584db2b 0.0.24 2017-10-24 21:18:16 -07:00
0e4e0d8899 0.0.23 2017-10-24 21:09:56 -07:00
a18a690417 Merge pull request #12 from Microsoft/motors
Converting motors to fixed instances
2017-10-25 06:09:27 +02:00
c9d57c5e8d enabling banner 2017-10-24 21:08:02 -07:00
7e9d42a571 reset motors on start 2017-10-24 20:28:31 -07:00
1b51320edb pausing while running motor 2017-10-24 20:20:07 -07:00
4f44238237 use fixed instances for motors 2017-10-24 20:16:33 -07:00
c8ffa0ded7 fixed test 2017-10-24 18:49:15 -07:00
6b07d5f716 0.0.22 2017-10-24 18:48:30 -07:00
8784e23b60 fixed build link 2017-10-24 17:01:36 -07:00
4b8409fbc0 0.0.21 2017-10-24 16:56:52 -07:00
3237978cba Merge pull request #4 from Microsoft/blockupdate
Blocks update
2017-10-24 16:56:32 -07:00
33c8902050 aligning groups with hardware name components 2017-10-24 16:52:13 -07:00
fa6c81cf80 buttons -> brick buttons 2017-10-24 16:25:03 -07:00
46175fc7db separating touch sensor stuff 2017-10-24 15:58:47 -07:00
e6ef86101f more renaming 2017-10-24 15:37:48 -07:00
c4d3d7634e fixed naming of sonar 2017-10-24 15:35:42 -07:00
b0380fbef8 more annotations 2017-10-24 15:33:28 -07:00
c85c68ab68 fixing color / gyro 2017-10-24 15:22:07 -07:00
334d5aca9a on/off field editors on motors 2017-10-24 15:03:21 -07:00
1330a0fb82 fixed gyro def 2017-10-24 14:54:36 -07:00
005447ce44 4 times more sensors\! 2017-10-24 19:58:52 +01:00
60d5271de2 Merge branch 'master' into blockupdate 2017-10-24 10:02:27 -07:00
e3ab6ace55 0.0.20 2017-10-24 10:01:49 -07:00
5f4488dea7 Merge pull request #3 from Microsoft/pxtupdate
Updated to latest of pxt / common
2017-10-24 10:00:41 -07:00
07dc3bdae1 fixing docs compilation 2017-10-24 09:55:38 -07:00
5d5d78ced0 compiled strings 2017-10-24 09:47:30 -07:00
fe46461c4c adding a few more blocks 2017-10-24 05:30:05 -07:00
ccda971fd1 Bump PXT and common packages 2017-10-24 12:50:00 +01:00
8fa6cf41ca updated build files 2017-10-23 13:43:59 -07:00
aa3c6d5fc0 bump pxt-core to 2.3.1, bump pxt-common-packages to 0.10.16, 2017-10-23 13:41:38 -07:00
6a719e7718 Use field toggle for switching the motor on / off 2017-10-04 17:04:26 -04:00
b18b8333d0 Remove button group 2017-10-03 02:31:06 -04:00
84d80131d4 Various UI fixes. Block refactoring and adding touch and color blocks. 2017-10-03 02:28:44 -04:00
4977358718 0.0.19 2017-09-15 10:06:47 -07:00
15b2ef6c92 Update theme.config 2017-09-15 10:06:33 -07:00
e0288ed741 bump pxt-core to 2.0.49, bump pxt-common-packages to 0.9.6, 2017-09-15 10:04:01 -07:00
df1caf9741 0.0.18 2017-09-01 16:50:18 -07:00
a755420d06 bump pxt-core to 2.0.34, bump pxt-common-packages to 0.9.3, 2017-09-01 16:50:13 -07:00
a139727fea 0.0.17 2017-08-28 21:52:26 -07:00
48e081e584 Update json strings 2017-08-28 21:52:09 -07:00
124ad5c915 bump pxt-core to 2.0.29, 2017-08-28 21:51:33 -07:00
75a571fda7 Update README.md 2017-08-14 14:35:03 -07:00
50 changed files with 1412 additions and 508 deletions

1
.gitignore vendored
View File

@ -31,3 +31,4 @@ videos/**
lib/ lib/
.vscode/ .vscode/
bin bin
scripts/out.*

View File

@ -1,8 +1,8 @@
# LEGO Mindstorms EV3 target for PXT # LEGO Mindstorms EV3 target for PXT
[![Build Status](https://ci2.dot.net/buildStatus/icon?job=Private/pxt_project_pink/master/pxt-ev3_Push)](https://ci2.dot.net/job/Private/job/pxt_project_pink/job/master/job/pxt-ev3_Push/) [![Build Status](https://ci2.dot.net/buildStatus/icon?job=Private/pxt_project_rainbow/master/pxt-ev3_Push)](https://ci2.dot.net/job/Private/job/pxt_project_rainbow/job/master/job/pxt-ev3_Push/)
This repo contains the editor target hosted at https://lego.makecode.com This repo contains the editor target hosted at https://d541eec2-1e96-4b7b-a223-da9d01d0337a.pxt.io/
## Local Dev setup ## Local Dev setup

View File

@ -3,9 +3,3 @@
## Reference #reference ## Reference #reference
* [Reference](/reference) * [Reference](/reference)
* [input](/reference/input)
* [light](/reference/light)
* [music](/reference/music)
* [pins](/reference/pins)
* [control](/reference/control)
* [serial](/reference/serial)

47
docs/maker.md Normal file
View File

@ -0,0 +1,47 @@
# Maker Activites
These six activities require the LEGO® MINDSTORMS® Education EV3 Core Set (45544). Supporting materials for teachers and middle school students are provided, offering everything teachers and students need to explore their inner makers as they follow the design process to solve open-ended, themed challenges...
* [Download Curriculum Materials](https://education.lego.com/en-us/downloads/mindstorms-ev3)
## Activites
```codecard
[
{
"name": "Sound Machine",
"description": "Create instruments with your EV3 Brick!",
"url":"/maker/sound-machine",
"cardType": "example",
"imageUrl": "/static/maker/sound-machine.png"
},
{
"name": "Sound Of Color",
"description": "Play different sounds based on the color",
"url":"/maker/sound-of-color",
"cardType": "example",
"imageUrl": "/static/maker/sound-of-color.png"
},
{
"name": "Security Gadget",
"description": "Raise the alarm when your brick is lifted!",
"url":"/maker/security-gadget",
"cardType": "example",
"imageUrl": "/static/maker/security-gadget.png"
},
{
"name": "Intruder Detector",
"description": "Raise the alarm when an intruder sneaks in",
"url":"/maker/intruder-detector",
"cardType": "example",
"imageUrl": "/static/maker/intruder-detector.png"
},
{
"name": "Puppet",
"description": "Build an automated puppet",
"url":"/maker/puppet",
"cardType": "example",
"imageUrl": "/static/maker/puppet.png"
}
]
```

View File

@ -0,0 +1,11 @@
# Intruder Detector
This program will activate an alarm when an object moves in front of the Ultrasonic Sensor.
TODO support for event when value changes
```blocks
input.ultrasonic4.onObjectNear(function () {
music.playSoundUntilDone(music.sounds(Sounds.PowerUp))
})
```

17
docs/maker/puppet.md Normal file
View File

@ -0,0 +1,17 @@
# Puppet
Use this program with the Programmable Brick and Large Motor.
```blocks
loops.forever(function () {
output.largeMotorA.setPower(30)
output.largeMotorA.on(true)
loops.pause(100)
output.largeMotorA.on(false)
music.playSoundUntilDone(music.sounds(Sounds.PowerUp))
output.largeMotorA.setPower(-30)
output.largeMotorA.on(true)
loops.pause(100)
output.largeMotorA.on(false)
})
```

View File

@ -0,0 +1,9 @@
# Security Gadget
This program will activate an alarm when an object is lifted from the Touch Sensor.
```blocks
input.touchSensor1.onEvent(TouchSensorEvent.Released, function () {
music.playSoundUntilDone(music.sounds(Sounds.PowerUp))
})
```

View File

@ -0,0 +1,12 @@
# Sound Machine
This example program combined with the small model will make a beat and rhythm on any surface when the program is run.
```blocks
loops.forever(function () {
output.motorA.on(50)
loops.pause(200)
output.motorA.on(100)
loops.pause(200)
})
```

View File

@ -0,0 +1,15 @@
# Sound Of Color
This program will play different sounds when the wheel is rotated. The sound is determined by which color is placed in front of the color Sensor.
```blocks
input.color3.onColorDetected(ColorSensorColor.Blue, function () {
music.playTone(Note.G4, music.beat(BeatFraction.Half))
})
input.color3.onColorDetected(ColorSensorColor.Red, function () {
music.playTone(Note.C5, music.beat(BeatFraction.Half))
})
input.color3.onColorDetected(ColorSensorColor.Green, function () {
music.playTone(Note.D5, music.beat(BeatFraction.Half))
})
```

View File

@ -1,19 +1,3 @@
# Reference # Reference
```namespaces TODO
input.onGesture(Gesture.Shake, () => {})
light.showRing('red red red red red red red red red red')
music.playTone(0, 0)
pins.pulseDuration()
control.runInBackground(() => {})
serial.writeLine("");
```
## See Also
[blocks](/blocks), [JavaScript](/javascript), [input](/reference/input), [light](/reference/light), [music](/reference/music),
[control](/reference/control), [pins](/reference/pins), [serial](/reference/serial)
```package
circuit-playground
```

BIN
docs/static/hero.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

74
docs/static/lego-logo.svg vendored Normal file
View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
width="141.73"
height="141.731"
viewBox="0 0 141.73 141.73101"
enable-background="new 0 0 265.365 141.732"
xml:space="preserve"
inkscape:version="0.91 r13725"
sodipodi:docname="lego-logo.svg"><metadata
id="metadata26"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs24" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1199"
inkscape:window-height="604"
id="namedview22"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="1.6520876"
inkscape:cx="101.03204"
inkscape:cy="98.819336"
inkscape:window-x="372"
inkscape:window-y="149"
inkscape:window-maximized="0"
inkscape:current-layer="g6" /><g
id="product_logo" /><g
id="guides" /><g
id="LEGO_LOGO_SMALL_RGB"><g
id="g6"><path
d="m 0.961,0.948 0,139.839 139.84,0 0,-139.839 -139.84,0 z"
id="path8"
inkscape:connector-curvature="0"
style="fill:#ffffff" /><path
d="m 0.961,0.948 0,139.839 139.84,0 0,-139.839 -139.84,0 z m 130.536,58.127 c -0.23,4.356 -1.617,9.786 -2.839,13.414 -4.917,14.609 -10.618,23.666 -23.821,23.666 -3.887,0 -10.783,-1.031 -13.324,-7.947 l -0.602,-1.641 -1.082,1.371 C 85.7,93.168 79.564,96.186 72.998,96.217 67.96,96.24 63.912,94.553 61.293,91.334 l -0.718,-0.883 -0.765,0.844 c -2.797,3.088 -7.668,4.859 -13.364,4.859 -4.473,0 -8.335,-1.521 -10.876,-4.277 l -0.692,-0.752 -0.72,0.727 c -2.825,2.852 -7.276,4.289 -12.873,4.158 -6.79,-0.162 -10.924,-3.951 -11.058,-10.141 -0.205,-9.543 9.031,-29.622 12.854,-35.727 2.482,-4.078 5.895,-6.055 10.438,-6.055 3.092,0 5.207,0.646 6.463,1.977 1.144,1.211 1.37,2.232 1.472,4.688 l 0.131,3.175 1.676,-2.7 c 4.054,-6.532 10.773,-7.434 17.43,-7.434 4.628,0 8.667,1.702 10.289,4.336 l 0.599,0.971 0.866,-0.737 c 3.431,-2.916 8.271,-4.521 13.629,-4.521 5.849,0 10.099,1.454 12.634,4.322 0.576,0.651 0.957,1.106 1.486,2.219 l 0.651,1.366 0.977,-1.155 c 3.712,-4.39 8.779,-6.615 15.067,-6.615 4.98,0 8.761,1.324 11.235,3.935 3.104,3.271 3.547,7.875 3.373,11.161 z"
id="path10"
inkscape:connector-curvature="0"
style="fill:#f6ec36" /><path
d="m 0.961,0.948 0,139.839 139.84,0 0,-139.839 -139.84,0 z M 135.435,64.44 c -0.633,5.089 -4.072,14.518 -5.899,18.286 -4.903,10.102 -11.453,17.863 -24.074,17.863 -6.742,0 -12.288,-2.15 -15.531,-6.283 -4.749,4.162 -10.627,6.342 -16.956,6.342 -4.876,0 -9.185,-1.408 -12.471,-4.012 -3.626,2.555 -8.52,3.98 -13.943,3.98 -4.53,0 -8.606,-1.244 -11.796,-3.543 -3.529,2.342 -8.154,3.506 -13.583,3.377 C 12.149,100.237 5.912,94.507 5.733,86.188 5.497,75.137 14.803,54.911 19.189,47.907 c 3.282,-5.392 8.292,-8.293 14.431,-8.293 6.663,0 9.078,1.903 10.267,4.326 5.141,-4.366 11.956,-4.617 16.808,-4.617 5.356,0 8.717,1.422 11.575,3.697 3.948,-2.368 8.477,-3.599 13.871,-3.599 6.897,0 12.021,1.604 15.595,5.137 4.168,-3.469 9.388,-5.05 15.23,-5.05 7.725,0 12.808,2.786 15.793,6.94 4.203,5.859 3.451,11.757 2.676,17.992 z"
id="path12"
inkscape:connector-curvature="0"
style="fill:#d01012" /><path
d="m 0,0 0,141.731 141.73,0 L 141.73,0 0,0 Z m 139.781,1.952 0,137.832 -137.83,0 0,-137.832 137.83,0 z"
id="path14"
inkscape:connector-curvature="0" /><path
d="m 134.752,42.53 0,-0.965 0.655,0 c 0.479,0 0.728,0.168 0.728,0.479 0,0.247 -0.16,0.486 -0.647,0.486 l -0.736,0 z m 2.351,2.002 -0.408,-0.708 c -0.354,-0.619 -0.452,-0.717 -0.755,-0.823 l 0,-0.019 c 0.596,-0.07 0.95,-0.453 0.95,-0.983 0,-0.56 -0.354,-0.984 -1.109,-0.984 l -1.754,0 0,3.519 0.727,0 0,-1.441 0.133,0 c 0.311,0 0.435,0.035 0.576,0.176 0.142,0.144 0.354,0.443 0.479,0.69 l 0.284,0.575 0.877,-0.002 0,0 z m -1.731,-4.497 c 1.51,0 2.737,1.218 2.737,2.726 0,1.508 -1.229,2.731 -2.737,2.731 -1.506,0 -2.72,-1.225 -2.72,-2.731 0,-1.506 1.214,-2.726 2.72,-2.726 z m 0,-0.67 c -1.877,0 -3.392,1.516 -3.392,3.396 0,1.879 1.515,3.394 3.392,3.394 1.883,0 3.397,-1.515 3.397,-3.394 0.002,-1.882 -1.514,-3.396 -3.397,-3.396 z"
id="path16"
inkscape:connector-curvature="0" /><path
d="m 116.889,43.002 c -7.325,0 -12.386,2.904 -15.812,6.961 -0.579,-1.214 -1.019,-1.746 -1.638,-2.447 -2.805,-3.17 -7.313,-4.649 -13.364,-4.649 -5.912,0 -10.841,1.846 -14.263,4.754 -1.777,-2.89 -6.013,-4.803 -11.121,-4.803 -6.674,0 -13.946,0.944 -18.261,7.896 -0.104,-2.503 -0.33,-3.828 -1.737,-5.317 -1.71,-1.81 -4.477,-2.282 -7.173,-2.282 -4.912,0 -8.605,2.146 -11.266,6.515 -3.859,6.163 -13.212,26.441 -13.001,36.263 0.137,6.344 4.393,10.916 12.01,11.096 5.952,0.143 10.62,-1.449 13.59,-4.447 2.665,2.896 6.731,4.594 11.596,4.594 5.417,0 10.868,-1.627 14.088,-5.182 2.712,3.332 6.979,5.271 12.468,5.244 7.175,-0.035 13.477,-3.438 17.593,-8.652 2.259,6.148 7.985,8.59 14.241,8.59 13.709,0 19.729,-9.428 24.748,-24.332 1.13,-3.357 2.639,-8.963 2.889,-13.672 0.413,-7.839 -2.903,-16.13 -15.587,-16.13 z M 25.672,80.477 c 7.093,-1.232 8.876,1.332 8.653,3.707 -0.669,7.109 -7.191,8.699 -12.854,8.566 -4.107,-0.1 -7.8,-1.98 -7.903,-6.748 -0.18,-8.342 8.328,-27.641 12.333,-34.038 1.85,-3.037 4.104,-4.539 7.698,-4.539 3.406,0 4.25,1.749 4.2,3.844 -0.134,5.589 -9.164,22.574 -12.127,29.208 z M 48.77,73.925 c -0.469,1.27 -1.357,3.93 -2.076,6.75 2.328,-0.582 4.074,-0.986 7.065,-0.914 3.408,0.084 5.586,1.496 5.586,4.314 0,6.832 -7.551,8.838 -12.789,8.838 -5.751,0 -10.803,-3.275 -10.803,-9.564 0,-7.373 3.997,-18.553 7.748,-26.001 4.606,-9.146 9.312,-10.362 17.419,-10.362 3.562,0 7.667,1.524 7.667,4.888 0,4.662 -3.95,6.44 -7.866,6.665 -1.672,0.096 -4.246,0.188 -5.786,0.079 0,0 -1.303,1.985 -2.688,5.523 7.252,-1.021 10.327,0.625 9.103,4.82 -1.657,5.667 -6.567,6.04 -12.58,4.964 z M 84.438,56.293 c -1.961,0 -3.244,1.242 -4.198,2.583 -2.102,2.952 -6.656,14.781 -7.365,19.64 -0.486,3.328 0.951,4.006 2.522,4.006 2.52,0 5.345,-2.666 6.309,-7.064 0,0 -4.797,-0.117 -3.475,-4.371 1.285,-4.128 3.723,-5.022 7.764,-5.188 7.961,-0.325 7.175,5.553 6.538,8.688 -2.069,10.18 -9.314,18.355 -19.562,18.355 -7.016,0 -11.371,-3.881 -11.371,-11.035 0,-5.098 2.529,-13.101 4.534,-17.784 4.267,-9.968 8.742,-16.944 20.143,-16.944 6.84,0 12.235,2.458 11.444,8.866 -0.58,4.703 -2.934,7.465 -7.21,7.799 -1.196,0.093 -6.089,-0.031 -4.466,-4.66 0.565,-1.619 0.799,-2.891 -1.607,-2.891 z m 43.057,8.413 c -1.205,6.002 -3.916,13.101 -6.859,18.392 -4.801,8.633 -10.633,9.842 -15.723,9.781 -5.093,-0.061 -10.83,-1.941 -10.874,-9.795 -0.031,-5.639 2.401,-13.598 4.466,-18.815 3.599,-9.458 7.277,-17.17 18.904,-17.031 13.559,0.161 11.141,12.219 10.086,17.468 z M 115.993,56.49 c -1.164,-0.016 -2.18,0.212 -3.093,1.62 -2.051,2.657 -8.047,19.042 -7.941,22.31 0.038,1.174 0.687,2.201 2.133,2.201 1.659,0.002 2.581,-1.145 3.396,-2.529 1.887,-3.193 7.193,-17.676 7.339,-21.297 0.043,-1.055 -0.133,-2.284 -1.834,-2.305 z"
id="path18"
inkscape:connector-curvature="0" /></g></g></svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
docs/static/lego_education_logo.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
docs/static/maker/intruder-detector.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
docs/static/maker/puppet.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

BIN
docs/static/maker/security-gadget.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
docs/static/maker/sound-machine.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

BIN
docs/static/maker/sound-of-color.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

View File

@ -1,36 +1,52 @@
{ {
"Array": "Add, remove, and replace items in lists.\n\nAdd, remove, and replace items in lists.", "Array": "Add, remove, and replace items in lists.\n\nAdd, remove, and replace items in lists.",
"Array.filter": "Returns the elements of an array that meet the condition specified in a callback function.", "Array.filter": "Return the elements of an array that meet the condition specified in a callback function.",
"Array.filter|param|callbackfn": "A function that accepts up to two arguments. The filter method calls the callbackfn function one time for each element in the array.", "Array.filter|param|callbackfn": "A function that accepts up to two arguments. The filter method calls the callbackfn function one time for each element in the array.",
"Array.get": "Gets the value at a particular index", "Array.get": "Get the value at a particular index",
"Array.get|param|index": "the zero-based position in the list of the item, eg: 0", "Array.get|param|index": "the zero-based position in the list of the item, eg: 0",
"Array.indexOf": "Returns the index of the first occurrence of a value in an array.", "Array.indexOf": "Return the index of the first occurrence of a value in an array.",
"Array.indexOf|param|fromIndex": "The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.", "Array.indexOf|param|fromIndex": "The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.",
"Array.indexOf|param|item": "The value to locate in the array.", "Array.indexOf|param|item": "The value to locate in the array.",
"Array.insertAt": "Insert the value at a particular index, increases length by 1", "Array.insertAt": "Insert the value at a particular index, increases length by 1",
"Array.insertAt|param|index": "the zero-based position in the list to insert the value, eg: 0", "Array.insertAt|param|index": "the zero-based position in the list to insert the value, eg: 0",
"Array.length": "Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.", "Array.length": "Get or set the length of an array. This number is one more than the index of the last element the array.",
"Array.map": "Calls a defined callback function on each element of an array, and returns an array that contains the results.", "Array.map": "Call a defined callback function on each element of an array, and return an array containing the results.",
"Array.map|param|callbackfn": "A function that accepts up to two arguments. The map method calls the callbackfn function one time for each element in the array.", "Array.map|param|callbackfn": "A function that accepts up to two arguments. The map method calls the callbackfn function one time for each element in the array.",
"Array.pop": "Removes the last element from an array and returns it.", "Array.pop": "Remove the last element from an array and return it.",
"Array.push": "Appends new elements to an array.", "Array.push": "Append a new element to an array.",
"Array.reduce": "Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.", "Array.reduce": "Call the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.",
"Array.reduce|param|callbackfn": "A function that accepts up to three arguments. The reduce method calls the callbackfn function one time for each element in the array.", "Array.reduce|param|callbackfn": "A function that accepts up to three arguments. The reduce method calls the callbackfn function one time for each element in the array.",
"Array.reduce|param|initialValue": "Initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.", "Array.reduce|param|initialValue": "Initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.",
"Array.removeAt": "Removes the object at position index.", "Array.removeAt": "Remove the element at a certain index.",
"Array.removeElement": "Removes the first occurence of an object. Returns true if removed.", "Array.removeElement": "Remove the first occurence of an object. Returns true if removed.",
"Array.reverse": "Reverses the elements in an Array. The first array element becomes the last, and the last array element becomes the first.", "Array.reverse": "Reverse the elements in an array. The first array element becomes the last, and the last array element becomes the first.",
"Array.set": "Stores the value at a particular index", "Array.set": "Store a value at a particular index",
"Array.set|param|index": "the zero-based position in the list to store the value, eg: 0", "Array.set|param|index": "the zero-based position in the list to store the value, eg: 0",
"Array.shift": "Removes the first element from an array and returns that element. This method changes the length of the array.", "Array.shift": "Remove the first element from an array and return it. This method changes the length of the array.",
"Array.slice": "Returns a section of an array.", "Array.slice": "Return a section of an array.",
"Array.slice|param|end": "The end of the specified portion of the array. eg: 0", "Array.slice|param|end": "The end of the specified portion of the array. eg: 0",
"Array.slice|param|start": "The beginning of the specified portion of the array. eg: 0", "Array.slice|param|start": "The beginning of the specified portion of the array. eg: 0",
"Array.sort": "Sorts the elements of an array in place and returns the array. The sort is not necessarily stable.", "Array.sort": "Sort the elements of an array in place and returns the array. The sort is not necessarily stable.",
"Array.splice": "Removes elements from an array.", "Array.splice": "Remove elements from an array.",
"Array.splice|param|deleteCount": "The number of elements to remove. eg: 0", "Array.splice|param|deleteCount": "The number of elements to remove. eg: 0",
"Array.splice|param|start": "The zero-based location in the array from which to start removing elements. eg: 0", "Array.splice|param|start": "The zero-based location in the array from which to start removing elements. eg: 0",
"Array.unshift": "Adds one element to the beginning of an array and returns the new length of the array.", "Array.unshift": "Add one element to the beginning of an array and return the new length of the array.",
"Boolean.toString": "Returns a string representation of an object.",
"Buffer.fill": "Fill (a fragment) of the buffer with given value.",
"Buffer.getNumber": "Read a number in specified format from the buffer.",
"Buffer.length": "Returns the length of a Buffer object.",
"Buffer.rotate": "Rotate buffer left in place.\n\n\n\nstart. eg: -1",
"Buffer.rotate|param|length": "number of elements in buffer. If negative, length is set as the buffer length minus",
"Buffer.rotate|param|offset": "number of bytes to shift; use negative value to shift right",
"Buffer.rotate|param|start": "start offset in buffer. Default is 0.",
"Buffer.setNumber": "Write a number in specified format in the buffer.",
"Buffer.shift": "Shift buffer left in place, with zero padding.\n\n\n\nstart. eg: -1",
"Buffer.shift|param|length": "number of elements in buffer. If negative, length is set as the buffer length minus",
"Buffer.shift|param|offset": "number of bytes to shift; use negative value to shift right",
"Buffer.shift|param|start": "start offset in buffer. Default is 0.",
"Buffer.slice": "Return a copy of a fragment of a buffer.",
"Buffer.toHex": "Convert a buffer to its hexadecimal representation.",
"Buffer.write": "Write contents of `src` at `dstOffset` in current buffer.",
"Math": "More complex operations with numbers.", "Math": "More complex operations with numbers.",
"Math.abs": "Returns the absolute value of a number (the value without regard to whether it is positive or negative).\nFor example, the absolute value of -5 is the same as the absolute value of 5.", "Math.abs": "Returns the absolute value of a number (the value without regard to whether it is positive or negative).\nFor example, the absolute value of -5 is the same as the absolute value of 5.",
"Math.abs|param|x": "A numeric expression for which the absolute value is needed.", "Math.abs|param|x": "A numeric expression for which the absolute value is needed.",
@ -91,23 +107,26 @@
"Math.tan|param|x": "An angle in radians", "Math.tan|param|x": "An angle in radians",
"Math.trunc": "Returns the number with the decimal part truncated.", "Math.trunc": "Returns the number with the decimal part truncated.",
"Math.trunc|param|x": "A numeric expression.", "Math.trunc|param|x": "A numeric expression.",
"Number.toString": "Returns a string representation of a number.",
"String": "Combine, split, and search text strings.\n\nCombine, split, and search text strings.", "String": "Combine, split, and search text strings.\n\nCombine, split, and search text strings.",
"String.charAt": "Returns the character at the specified index.", "String.charAt": "Return the character at the specified index.",
"String.charAt|param|index": "The zero-based index of the desired character.", "String.charAt|param|index": "The zero-based index of the desired character.",
"String.charCodeAt": "Returns the Unicode value of the character at the specified location.", "String.charCodeAt": "Return the Unicode value of the character at the specified location.",
"String.charCodeAt|param|index": "The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.", "String.charCodeAt|param|index": "The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.",
"String.compare": "Determines whether relative order of two strings (in ASCII encoding).", "String.compare": "See how the order of characters in two strings is different (in ASCII encoding).",
"String.compare|param|that": "String to compare to target string", "String.compare|param|that": "String to compare to target string",
"String.concat": "Returns a string that contains the concatenation of two or more strings.", "String.concat": "Returns a string that contains the concatenation of two or more strings.",
"String.concat|param|other": "The string to append to the end of the string.", "String.concat|param|other": "The string to append to the end of the string.",
"String.fromCharCode": "Make a string from the given ASCII character code.", "String.fromCharCode": "Make a string from the given ASCII character code.",
"String.isEmpty": "Returns a value indicating if the string is empty", "String.isEmpty": "Returns a value indicating if the string is empty",
"String.length": "Returns the length of a String object.", "String.length": "Returns the length of a String object.",
"String.substr": "Return substring of the current string.", "String.substr": "Return a substring of the current string.",
"String.substr|param|length": "number of characters to extract", "String.substr|param|length": "number of characters to extract",
"String.substr|param|start": "first character index; can be negative from counting from the end, eg:0", "String.substr|param|start": "first character index; can be negative from counting from the end, eg:0",
"control": "Program controls and events.", "control": "Program controls and events.",
"control.assert": "Display specified error code and stop the program.", "control.AnimationQueue.cancel": "Cancels the current running animation and clears the queue",
"control.AnimationQueue.runUntilDone": "Runs 'render' in a loop until it returns false or the 'stop' function is called",
"control.assert": "Display an error code and stop the program when the assertion is `false`.",
"control.deviceSerialNumber": "Derive a unique, consistent serial number of this device from internal data.", "control.deviceSerialNumber": "Derive a unique, consistent serial number of this device from internal data.",
"control.millis": "Gets the number of milliseconds elapsed since power on.", "control.millis": "Gets the number of milliseconds elapsed since power on.",
"control.onEvent": "Run code when a registered event happens.", "control.onEvent": "Run code when a registered event happens.",
@ -119,9 +138,13 @@
"control.waitForEvent": "Blocks the calling thread until the specified event is raised.", "control.waitForEvent": "Blocks the calling thread until the specified event is raised.",
"control.waitMicros": "Block the current fiber for the given microseconds", "control.waitMicros": "Block the current fiber for the given microseconds",
"control.waitMicros|param|micros": "number of micro-seconds to wait. eg: 4", "control.waitMicros|param|micros": "number of micro-seconds to wait. eg: 4",
"hex": "Tagged hex literal converter",
"loops.forever": "Repeats the code forever in the background. On each iteration, allows other codes to run.", "loops.forever": "Repeats the code forever in the background. On each iteration, allows other codes to run.",
"loops.pause": "Pause for the specified time in milliseconds", "loops.pause": "Pause for the specified time in milliseconds",
"loops.pause|param|ms": "how long to pause for, eg: 100, 200, 500, 1000, 2000", "loops.pause|param|ms": "how long to pause for, eg: 100, 200, 500, 1000, 2000",
"loops.timePicker": "Get the time field editor",
"loops.timePicker|param|ms": "time duration in milliseconds, eg: 500, 1000",
"parseInt": "Convert a string to an integer.",
"serial": "Reading and writing data over a serial connection.", "serial": "Reading and writing data over a serial connection.",
"serial.writeBuffer": "Send a buffer across the serial connection.", "serial.writeBuffer": "Send a buffer across the serial connection.",
"serial.writeLine": "Write a line of text to the serial port.", "serial.writeLine": "Write a line of text to the serial port.",

View File

@ -19,6 +19,7 @@
"String.length|block": "length of %VALUE", "String.length|block": "length of %VALUE",
"String.substr|block": "substring of %this=text|from %start|of length %length", "String.substr|block": "substring of %this=text|from %start|of length %length",
"String|block": "String", "String|block": "String",
"control.assert|block": "assert %cond|with value %code",
"control.deviceSerialNumber|block": "device serial number", "control.deviceSerialNumber|block": "device serial number",
"control.millis|block": "millis (ms)", "control.millis|block": "millis (ms)",
"control.onEvent|block": "on event|from %src|with value %value", "control.onEvent|block": "on event|from %src|with value %value",
@ -29,8 +30,10 @@
"control.waitMicros|block": "wait (µs)%micros", "control.waitMicros|block": "wait (µs)%micros",
"control|block": "control", "control|block": "control",
"loops.forever|block": "forever", "loops.forever|block": "forever",
"loops.pause|block": "pause (ms) %pause", "loops.pause|block": "pause %ms=timePicker|ms",
"loops.timePicker|block": "%ms",
"loops|block": "loops", "loops|block": "loops",
"parseInt|block": "parse to integer %text",
"serial.writeBuffer|block": "serial|write buffer %buffer", "serial.writeBuffer|block": "serial|write buffer %buffer",
"serial.writeLine|block": "serial|write line %text", "serial.writeLine|block": "serial|write line %text",
"serial.writeNumber|block": "serial|write number %value", "serial.writeNumber|block": "serial|write number %value",
@ -39,9 +42,13 @@
"serial|block": "serial", "serial|block": "serial",
"{id:category}Array": "Array", "{id:category}Array": "Array",
"{id:category}Arrays": "Arrays", "{id:category}Arrays": "Arrays",
"{id:category}Boolean": "Boolean",
"{id:category}Buffer": "Buffer",
"{id:category}Control": "Control", "{id:category}Control": "Control",
"{id:category}Helpers": "Helpers",
"{id:category}Loops": "Loops", "{id:category}Loops": "Loops",
"{id:category}Math": "Math", "{id:category}Math": "Math",
"{id:category}Number": "Number",
"{id:category}Serial": "Serial", "{id:category}Serial": "Serial",
"{id:category}String": "String", "{id:category}String": "String",
"{id:category}Text": "Text" "{id:category}Text": "Text"

11
libs/base/shims.d.ts vendored
View File

@ -70,7 +70,7 @@ declare namespace loops {
* Repeats the code forever in the background. On each iteration, allows other codes to run. * Repeats the code forever in the background. On each iteration, allows other codes to run.
* @param body code to execute * @param body code to execute
*/ */
//% help=loops/forever weight=100 blockGap=8 //% help=loops/forever weight=100 afterOnStart=true
//% blockId=forever block="forever" blockAllowMultiple=1 shim=loops::forever //% blockId=forever block="forever" blockAllowMultiple=1 shim=loops::forever
function forever(a: () => void): void; function forever(a: () => void): void;
@ -79,7 +79,7 @@ declare namespace loops {
* @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000 * @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000
*/ */
//% help=loops/pause weight=99 //% help=loops/pause weight=99
//% async block="pause (ms) %pause" //% async block="pause %ms=timePicker|ms"
//% blockId=device_pause shim=loops::pause //% blockId=device_pause shim=loops::pause
function pause(ms: int32): void; function pause(ms: int32): void;
} }
@ -120,7 +120,7 @@ declare namespace control {
/** /**
* Run other code in the background. * Run other code in the background.
*/ */
//% help=control/run-in-background blockAllowMultiple=1 //% help=control/run-in-background blockAllowMultiple=1 afterOnStart=true
//% blockId="control_run_in_background" block="run in background" blockGap=8 shim=control::runInBackground //% blockId="control_run_in_background" block="run in background" blockGap=8 shim=control::runInBackground
function runInBackground(a: () => void): void; function runInBackground(a: () => void): void;
@ -134,7 +134,8 @@ declare namespace control {
/** /**
* Derive a unique, consistent serial number of this device from internal data. * Derive a unique, consistent serial number of this device from internal data.
*/ */
//% blockId="control_device_serial_number" block="device serial number" weight=9 shim=control::deviceSerialNumber //% blockId="control_device_serial_number" block="device serial number" weight=9
//% help=control/device-serial-number shim=control::deviceSerialNumber
function deviceSerialNumber(): int32; function deviceSerialNumber(): int32;
} }
declare namespace serial { declare namespace serial {
@ -150,7 +151,7 @@ declare namespace serial {
/** /**
* Send a buffer across the serial connection. * Send a buffer across the serial connection.
*/ */
//% help=serial/write-buffer advanced=true weight=6 //% help=serial/write-buffer weight=6
//% blockId=serial_writebuffer block="serial|write buffer %buffer" shim=serial::writeBuffer //% blockId=serial_writebuffer block="serial|write buffer %buffer" shim=serial::writeBuffer
function writeBuffer(buffer: Buffer): void; function writeBuffer(buffer: Buffer): void;
} }

View File

@ -1,4 +1,15 @@
{ {
"ButtonEvent": "User interaction on buttons",
"Draw": "Drawing modes",
"LightsPattern": "Patterns for lights under the buttons.",
"MMap.getNumber": "Read a number in specified format from the buffer.",
"MMap.ioctl": "Perform ioctl(2) on the underlaying file",
"MMap.length": "Returns the length of a Buffer object.",
"MMap.read": "Perform read(2) on the underlaying file",
"MMap.setNumber": "Write a number in specified format in the buffer.",
"MMap.slice": "Read a range of bytes into a buffer.",
"MMap.write": "Perform write(2) on the underlaying file",
"TouchSensorEvent": "Touch sensor interactions",
"control": "Program controls and events.", "control": "Program controls and events.",
"control.allocateNotifyEvent": "Allocates the next user notification event", "control.allocateNotifyEvent": "Allocates the next user notification event",
"control.deviceFirmwareVersion": "Determine the version of system software currently running.", "control.deviceFirmwareVersion": "Determine the version of system software currently running.",
@ -7,46 +18,73 @@
"control.raiseEvent": "Announce that an event happened to registered handlers.", "control.raiseEvent": "Announce that an event happened to registered handlers.",
"control.raiseEvent|param|src": "ID of the Component that generated the event", "control.raiseEvent|param|src": "ID of the Component that generated the event",
"control.raiseEvent|param|value": "Component specific code indicating the cause of the event.", "control.raiseEvent|param|value": "Component specific code indicating the cause of the event.",
"input": "Respond to and read data from buttons and sensors.",
"input.Button": "Generic button class, for device buttons and sensors.", "input.Button": "Generic button class, for device buttons and sensors.",
"input.buttonDown": "Down button.", "input.Button.isPressed": "Check if button is currently pressed or not.",
"input.buttonEnter": "Enter button.", "input.Button.onEvent": "Do something when a button or sensor is clicked, up or down.",
"input.buttonLeft": "Left button.", "input.Button.onEvent|param|body": "code to run when the event is raised",
"input.buttonRight": "Right button.", "input.Button.wasPressed": "See if the button was pressed again since the last time you checked.",
"input.buttonUp": "Up button.", "input.ColorSensor.ambientLight": "Get current ambient light value from the color sensor.",
"input.remoteBottomLeft": "Remote bottom-left button.", "input.ColorSensor.color": "Get the current color from the color sensor.",
"input.remoteBottomRight": "Remote bottom-right button.", "input.ColorSensor.onColorDetected": "Registers code to run when the given color is detected",
"input.remoteCenter": "Remote beacon (center) button.", "input.ColorSensor.onColorDetected|param|color": "the color to dtect",
"input.remoteTopLeft": "Remote top-left button.", "input.ColorSensor.onColorDetected|param|handler": "the code to run when detected",
"input.remoteTopRight": "Remote top-right button.", "input.ColorSensor.reflectedLight": "Get current reflected light value from the color sensor.",
"input.GyroSensor.angle": "Get the current angle from the gyroscope.",
"input.GyroSensor.rate": "Get the current rotation rate from the gyroscope.",
"input.InfraredSensor.onObjectNear": "Registers code to run when an object is getting near.",
"input.InfraredSensor.onObjectNear|param|handler": "the code to run when detected",
"input.InfraredSensor.proximity": "Get the promixity measured by the infrared sensor, from ``0`` (close) to ``100`` (far)",
"input.InfraredSensor.remoteCommand": "Get the remote commandreceived the infrared sensor.",
"input.RemoteInfraredBeaconButton.isPressed": "Check if a remote button is currently pressed or not.",
"input.RemoteInfraredBeaconButton.onEvent": "Do something when a button or sensor is clicked, up or down",
"input.RemoteInfraredBeaconButton.onEvent|param|body": "code to run when the event is raised",
"input.RemoteInfraredBeaconButton.wasPressed": "See if the remote button was pressed again since the last time you checked.",
"input.TouchSensor.isTouched": "Check if touch sensor is touched.",
"input.TouchSensor.onEvent": "Do something when a touch sensor is touched...",
"input.TouchSensor.onEvent|param|body": "code to run when the event is raised",
"input.UltraSonicSensor.distance": "Gets the distance from the sonar in millimeters",
"input.UltraSonicSensor.onObjectNear": "Registers code to run when the given color is close",
"input.UltraSonicSensor.onObjectNear|param|handler": "the code to run when detected",
"input.buttonDown": "Down button on the EV3 Brick.",
"input.buttonEnter": "Enter button on the EV3 Brick.",
"input.buttonLeft": "Left button on the EV3 Brick.",
"input.buttonRight": "Right button on the EV3 Brick.",
"input.buttonUp": "Up button on the EV3 Brick.",
"input.remoteButtonBottomLeft": "Remote bottom-left button.",
"input.remoteButtonBottomRight": "Remote bottom-right button.",
"input.remoteButtonCenter": "Remote beacon (center) button.",
"input.remoteButtonTopLeft": "Remote top-left button.",
"input.remoteButtonTopRight": "Remote top-right button.",
"output.Motor.clearCount": "Clears the motor count",
"output.Motor.count": "Gets motor step count.",
"output.Motor.on": "Power on or off the motor.",
"output.Motor.reset": "Resets the motor.",
"output.Motor.setBrake": "Sets the automatic brake on or off when the motor is off",
"output.Motor.setBrake|param|brake": "a value indicating if the motor should break when off",
"output.Motor.setPower": "Sets the motor power level from ``-100`` to ``100``.",
"output.Motor.setPower|param|power": "the desired speed to use. eg: 50",
"output.Motor.setReversed": "Reverses the motor polarity",
"output.Motor.speed": "Gets motor actual speed.",
"output.Motor.tachoCount": "Gets motor tacho count.",
"output.createBuffer": "Create a new zero-initialized buffer.", "output.createBuffer": "Create a new zero-initialized buffer.",
"output.createBuffer|param|size": "number of bytes in the buffer", "output.createBuffer|param|size": "number of bytes in the buffer",
"output.getCurrentSpeed": "Get motor speed.", "output.pattern": "Pattern block.",
"output.getCurrentSpeed|param|out": "the output connection that the motor is connected to", "output.pattern|param|pattern": "the lights pattern to use. eg: LightsPattern.Green",
"output.getPattern": "Pattern block.", "output.setStatusLight": "Set lights.",
"output.getPattern|param|pattern": "the lights pattern to use. eg: LightsPattern.Green", "output.setStatusLight|param|pattern": "the lights pattern to use.",
"output.setLights": "Set lights.", "output.stopAllMotors": "Stops all motors",
"output.setLights|param|pattern": "the lights pattern to use.",
"output.setPower": "Set motor power.",
"output.setPower|param|out": "the output connection that the motor is connected to",
"output.setPower|param|power": "the desired power to use. eg: 100",
"output.setSpeed": "Set motor speed.",
"output.setSpeed|param|out": "the output connection that the motor is connected to",
"output.setSpeed|param|speed": "the desired speed to use. eg: 100",
"output.start": "Turn motor on.",
"output.start|param|out": "the output connection that the motor is connected to",
"output.stop": "Turn motor off.",
"output.stop|param|out": "the output connection that the motor is connected to",
"output.turn": "Turn a motor on for a specified number of milliseconds.",
"output.turn|param|ms": "the number of milliseconds to turn the motor on, eg: 500",
"output.turn|param|out": "the output connection that the motor is connected to",
"output.turn|param|useBrake": "whether or not to use the brake, defaults to false",
"screen.clear": "Clear screen and reset font to normal.", "screen.clear": "Clear screen and reset font to normal.",
"screen.doubleIcon": "Double size of an icon.", "screen.doubleIcon": "Double size of an icon.",
"screen.drawIcon": "Draw an icon on the screen.", "screen.drawIcon": "Draw an icon on the screen.",
"screen.drawText": "Show text on the screen.", "screen.print": "Show text on the screen.",
"screen.drawText|param|text": "the text to print on the screen, eg: \"Hello world\"", "screen.print|param|text": "the text to print on the screen, eg: \"Hello world\"",
"screen.drawText|param|x": "the starting position's x coordinate, eg: 0", "screen.print|param|x": "the starting position's x coordinate, eg: 0",
"screen.drawText|param|y": "the starting position's x coordinate, eg: 0", "screen.print|param|y": "the starting position's x coordinate, eg: 0",
"screen.setPixel": "Sets a pixel on or off",
"screen.setPixel|param|on": "a value indicating if the pixel should be on or off",
"screen.setPixel|param|x": "the starting position's x coordinate, eg: 0",
"screen.setPixel|param|y": "the starting position's x coordinate, eg: 0",
"serial": "Reading and writing data over a serial connection.", "serial": "Reading and writing data over a serial connection.",
"serial.writeDmesg": "Send DMESG debug buffer over serial." "serial.writeDmesg": "Send DMESG debug buffer over serial."
} }

View File

@ -1,8 +1,15 @@
{ {
"ButtonEvent.Click|block": "click", "ButtonEvent.Click|block": "click",
"ButtonEvent.Down|block": "down", "ButtonEvent.Down|block": "down",
"ButtonEvent.LongClick|block": "long click",
"ButtonEvent.Up|block": "up", "ButtonEvent.Up|block": "up",
"ColorSensorColor.Black|block": "black",
"ColorSensorColor.Blue|block": "blue",
"ColorSensorColor.Brown|block": "brown",
"ColorSensorColor.Green|block": "green",
"ColorSensorColor.None|block": "none",
"ColorSensorColor.Red|block": "red",
"ColorSensorColor.White|block": "white",
"ColorSensorColor.Yellow|block": "yellow",
"LightsPattern.GreenFlash|block": "Flashing Green", "LightsPattern.GreenFlash|block": "Flashing Green",
"LightsPattern.GreenPulse|block": "Pulsing Green", "LightsPattern.GreenPulse|block": "Pulsing Green",
"LightsPattern.Green|block": "Green", "LightsPattern.Green|block": "Green",
@ -13,37 +20,103 @@
"LightsPattern.RedFlash|block": "Flashing Red", "LightsPattern.RedFlash|block": "Flashing Red",
"LightsPattern.RedPulse|block": "Pulsing Red", "LightsPattern.RedPulse|block": "Pulsing Red",
"LightsPattern.Red|block": "Red", "LightsPattern.Red|block": "Red",
"Output.ALL|block": "All",
"Output.A|block": "A",
"Output.B|block": "B",
"Output.C|block": "C",
"Output.D|block": "D",
"PromixityEvent.ObjectDetected|block": "object detected",
"PromixityEvent.ObjectNear|block": "object near",
"TouchSensorEvent.Bumped|block": "bumped",
"TouchSensorEvent.Pressed|block": "pressed",
"TouchSensorEvent.Released|block": "released",
"control.raiseEvent|block": "raise event|from %src|with value %value", "control.raiseEvent|block": "raise event|from %src|with value %value",
"control|block": "control", "control|block": "control",
"input.buttonDown|block": "button down", "input.Button.isPressed|block": "%button|is pressed",
"input.buttonEnter|block": "button enter", "input.Button.onEvent|block": "on %button|%event",
"input.buttonLeft|block": "button left", "input.Button.wasPressed|block": "%button|was pressed",
"input.buttonRight|block": "button right", "input.ColorSensor.ambientLight|block": "%color| ambient light",
"input.buttonUp|block": "button up", "input.ColorSensor.color|block": "%color| color",
"input.remoteBottomLeft|block": "remote bottom-left", "input.ColorSensor.onColorDetected|block": "on %sensor|detected %color",
"input.remoteBottomRight|block": "remote bottom-right", "input.ColorSensor.reflectedLight|block": "%color| reflected light",
"input.remoteCenter|block": "remote center", "input.GyroSensor.angle|block": "%sensor|angle",
"input.remoteTopLeft|block": "remote top-left", "input.GyroSensor.rate|block": "%sensor|rotation rate",
"input.remoteTopRight|block": "remote top-right", "input.InfraredSensor.onObjectNear|block": "on %sensor|object near",
"input.InfraredSensor.proximity|block": "%infrared|proximity",
"input.InfraredSensor.remoteCommand|block": "%infrared|remote command",
"input.RemoteInfraredBeaconButton.isPressed|block": "%button|is pressed",
"input.RemoteInfraredBeaconButton.onEvent|block": "on %button|%event",
"input.RemoteInfraredBeaconButton.wasPressed|block": "%button|was pressed",
"input.TouchSensor.isTouched|block": "%sensor|is touched",
"input.TouchSensor.onEvent|block": "on %sensor|%event",
"input.UltraSonicSensor.distance|block": "%sensor|distance",
"input.UltraSonicSensor.onObjectNear|block": "on %sensor|object near",
"input.buttonDown|block": "brick button down",
"input.buttonEnter|block": "brick button enter",
"input.buttonLeft|block": "brick button left",
"input.buttonRight|block": "brick button right",
"input.buttonUp|block": "brick button up",
"input.color1|block": "color sensor 1",
"input.color2|block": "color sensor 2",
"input.color3|block": "color sensor 3",
"input.color4|block": "color sensor 4",
"input.gyro1|block": "gyro sensor 1",
"input.gyro2|block": "gyro sensor 2",
"input.gyro3|block": "gyro sensor 3",
"input.gyro4|block": "gyro sensor 4",
"input.infraredSensor1|block": "infrared sensor 1",
"input.infraredSensor2|block": "infrared sensor 2",
"input.infraredSensor3|block": "infrared sensor 3",
"input.infraredSensor4|block": "infrared sensor 4",
"input.remoteButtonBottomLeft|block": "remote button bottom-left",
"input.remoteButtonBottomRight|block": "remote button bottom-right",
"input.remoteButtonCenter|block": "remote button center",
"input.remoteButtonTopLeft|block": "remote button top-left",
"input.remoteButtonTopRight|block": "remote button top-right",
"input.touchSensor1|block": "touch sensor 1",
"input.touchSensor2|block": "touch sensor 2",
"input.touchSensor3|block": "touch sensor 3",
"input.touchSensor4|block": "touch sensor 4",
"input.ultrasonic1|block": "ultrasonic sensor 1",
"input.ultrasonic2|block": "ultrasonic sensor 2",
"input.ultrasonic3|block": "ultrasonic sensor 3",
"input.ultrasonic4|block": "ultrasonic sensor 4",
"input|block": "input", "input|block": "input",
"output.getCurrentSpeed|block": "motor %out|speed", "output.Motor.count|block": "%motor|count",
"output.getPattern|block": "%pattern", "output.Motor.on|block": "%motor|%onOrOff",
"output.setLights|block": "set status light %pattern=led_pattern", "output.Motor.setBrake|block": "%motor|set brake %brake",
"output.setPower|block": "set motor %out| power to %power", "output.Motor.setPower|block": "%motor|set power to %speed",
"output.setSpeed|block": "set motor %out| speed to %speed", "output.Motor.setReversed|block": "%motor|set reversed %reversed",
"output.start|block": "turn motor %out|on", "output.Motor.speed|block": "%motor|speed",
"output.stop|block": "turn motor %out|off", "output.Motor.tachoCount|block": "%motor|tacho count",
"output.turn|block": "turn motor %out| on for %ms|milliseconds", "output.largeMotorA|block": "large motor A",
"output.largeMotorB|block": "large motor B",
"output.largeMotorC|block": "large motor C",
"output.largeMotorD|block": "large motor D",
"output.mediumMotorA|block": "medium motor A",
"output.mediumMotorB|block": "medium motor B",
"output.mediumMotorC|block": "medium motor C",
"output.mediumMotorD|block": "medium motor D",
"output.pattern|block": "%pattern",
"output.setStatusLight|block": "set status light %pattern=led_pattern",
"output.stopAllMotors|block": "stop all motors",
"output|block": "output", "output|block": "output",
"screen.drawText|block": "print %text| at x: %x| y: %y", "screen.print|block": "print %text| at x: %x| y: %y",
"screen.setPixel|block": "set pixel %on| at x: %x| y: %y",
"screen|block": "screen", "screen|block": "screen",
"serial|block": "serial", "serial|block": "serial",
"{id:category}Control": "Control", "{id:category}Control": "Control",
"{id:category}Input": "Input", "{id:category}Input": "Input",
"{id:category}MMap": "MMap",
"{id:category}Output": "Output", "{id:category}Output": "Output",
"{id:category}Screen": "Screen", "{id:category}Screen": "Screen",
"{id:category}Serial": "Serial", "{id:category}Serial": "Serial",
"{id:group}Lights": "Lights", "{id:group}Brick": "Brick",
"{id:group}Color Sensor": "Color Sensor",
"{id:group}Gyro Sensor": "Gyro Sensor",
"{id:group}Infrared Sensor": "Infrared Sensor",
"{id:group}Motors": "Motors", "{id:group}Motors": "Motors",
"{id:group}Screen": "Screen" "{id:group}Remote Infrared Beacon": "Remote Infrared Beacon",
"{id:group}Touch Sensor": "Touch Sensor",
"{id:group}Ultrasonic Sensor": "Ultrasonic Sensor"
} }

View File

@ -4,34 +4,34 @@
*/ */
const enum LightsPattern { const enum LightsPattern {
//% block=Off enumval=0 //% block=Off enumval=0
//% blockIdentity=output.getPattern //% blockIdentity=output.pattern
Off = 0, Off = 0,
//% block=Green enumval=1 //% block=Green enumval=1
//% blockIdentity=output.getPattern //% blockIdentity=output.pattern
Green = 1, Green = 1,
//% block=Red enumval=2 //% block=Red enumval=2
//% blockIdentity=output.getPattern //% blockIdentity=output.pattern
Red = 2, Red = 2,
//% block=Orange enumval=3 //% block=Orange enumval=3
//% blockIdentity=output.getPattern //% blockIdentity=output.pattern
Orange = 3, Orange = 3,
//% block="Flashing Green" enumval=4 //% block="Flashing Green" enumval=4
//% blockIdentity=output.getPattern //% blockIdentity=output.pattern
GreenFlash = 4, GreenFlash = 4,
//% block="Flashing Red" enumval=5 //% block="Flashing Red" enumval=5
//% blockIdentity=output.getPattern //% blockIdentity=output.pattern
RedFlash = 5, RedFlash = 5,
//% block="Flashing Orange" enumval=6 //% block="Flashing Orange" enumval=6
//% blockIdentity=output.getPattern //% blockIdentity=output.pattern
OrangeFlash = 6, OrangeFlash = 6,
//% block="Pulsing Green" enumval=7 //% block="Pulsing Green" enumval=7
//% blockIdentity=output.getPattern //% blockIdentity=output.pattern
GreenPulse = 7, GreenPulse = 7,
//% block="Pulsing Red" enumval=8 //% block="Pulsing Red" enumval=8
//% blockIdentity=output.getPattern //% blockIdentity=output.pattern
RedPulse = 8, RedPulse = 8,
//% block="Pulsing Orange" enumval=9 //% block="Pulsing Orange" enumval=9
//% blockIdentity=output.getPattern //% blockIdentity=output.pattern
OrangePulse = 9, OrangePulse = 9,
} }
@ -41,8 +41,6 @@ const enum LightsPattern {
const enum ButtonEvent { const enum ButtonEvent {
//% block="click" //% block="click"
Click = 1, Click = 1,
//% block="long click"
LongClick = 2,
//% block="up" //% block="up"
Up = 3, Up = 3,
//% block="down" //% block="down"
@ -67,7 +65,7 @@ namespace input {
} }
//% hidden //% hidden
update(curr: boolean) { _update(curr: boolean) {
if (this._isPressed == curr) return if (this._isPressed == curr) return
this._isPressed = curr this._isPressed = curr
if (curr) { if (curr) {
@ -76,7 +74,8 @@ namespace input {
} else { } else {
control.raiseEvent(this._id, ButtonEvent.Up) control.raiseEvent(this._id, ButtonEvent.Up)
let delta = control.millis() - this.downTime let delta = control.millis() - this.downTime
control.raiseEvent(this._id, delta > 500 ? ButtonEvent.LongClick : ButtonEvent.Click) control.raiseEvent(this._id, ButtonEvent.Click)
//control.raiseEvent(this._id, delta > 500 ? ButtonEvent.LongClick : ButtonEvent.Click)
} }
} }
@ -84,16 +83,13 @@ namespace input {
* Check if button is currently pressed or not. * Check if button is currently pressed or not.
* @param button the button to query the request * @param button the button to query the request
*/ */
//% help=input/button/is-pressed weight=79 //% help=input/button/is-pressed
//% block="%button|is pressed" //% block="%button|is pressed"
//% blockId=buttonIsPressed //% blockId=buttonIsPressed
//% blockGap=8 //% parts="brick"
//% parts="buttonpair"
//% blockNamespace=input //% blockNamespace=input
//% group="Brick buttons" //% weight=81 blockGap=8
//% button.fieldEditor="gridpicker" //% group="Brick"
//% button.fieldOptions.width=220
//% button.fieldOptions.columns=3
isPressed() { isPressed() {
return this._isPressed return this._isPressed
} }
@ -102,15 +98,13 @@ namespace input {
* See if the button was pressed again since the last time you checked. * See if the button was pressed again since the last time you checked.
* @param button the button to query the request * @param button the button to query the request
*/ */
//% help=input/button/was-pressed weight=78 //% help=input/button/was-pressed
//% block="%button|was pressed" //% block="%button|was pressed"
//% blockId=buttonWasPressed //% blockId=buttonWasPressed
//% parts="buttonpair" blockGap=8 //% parts="brick"
//% blockNamespace=input advanced=true //% blockNamespace=input
//% group="Brick buttons" //% weight=80 blockGap=8
//% button.fieldEditor="gridpicker" //% group="Brick"
//% button.fieldOptions.width=220
//% button.fieldOptions.columns=3
wasPressed() { wasPressed() {
const r = this._wasPressed const r = this._wasPressed
this._wasPressed = false this._wasPressed = false
@ -118,19 +112,17 @@ namespace input {
} }
/** /**
* Do something when a button or sensor is clicked, double clicked, etc... * Do something when a button or sensor is clicked, up or down.
* @param button the button that needs to be clicked or used * @param button the button that needs to be clicked or used
* @param event the kind of button gesture that needs to be detected * @param event the kind of button gesture that needs to be detected
* @param body code to run when the event is raised * @param body code to run when the event is raised
*/ */
//% help=input/button/on-event weight=99 blockGap=8 //% help=input/button/on-event
//% blockId=buttonEvent block="on %button|%event" //% blockId=buttonEvent block="on %button|%event"
//% parts="buttonpair" //% parts="brick"
//% blockNamespace=input //% blockNamespace=input
//% group="Brick buttons" //% weight=99 blockGap=8
//% button.fieldEditor="gridpicker" //% group="Brick"
//% button.fieldOptions.width=220
//% button.fieldOptions.columns=3
onEvent(ev: ButtonEvent, body: () => void) { onEvent(ev: ButtonEvent, body: () => void) {
control.onEvent(this._id, ev, body) control.onEvent(this._id, ev, body)
} }
@ -167,7 +159,7 @@ namespace input {
if (curr & DAL.BUTTON_ID_ESCAPE) if (curr & DAL.BUTTON_ID_ESCAPE)
control.reset() control.reset()
for (let b of buttons) for (let b of buttons)
b.update(!!(curr & b.mask)) b._update(!!(curr & b.mask))
}) })
control.dmesg("runtime started, " + control.deviceFirmwareVersion()) control.dmesg("runtime started, " + control.deviceFirmwareVersion())
} }
@ -184,35 +176,36 @@ namespace input {
initBtns() // always ON as it handles ESCAPE button initBtns() // always ON as it handles ESCAPE button
/** /**
* Left button. * Enter button on the EV3 Brick.
*/ */
//% whenUsed block="button left" weight=95 fixedInstance //% whenUsed block="brick button enter" weight=95 fixedInstance
export const buttonEnter: Button = new DevButton(DAL.BUTTON_ID_ENTER)
/**
* Left button on the EV3 Brick.
*/
//% whenUsed block="brick button left" weight=95 fixedInstance
export const buttonLeft: Button = new DevButton(DAL.BUTTON_ID_LEFT) export const buttonLeft: Button = new DevButton(DAL.BUTTON_ID_LEFT)
/** /**
* Right button. * Right button on the EV3 Brick.
*/ */
//% whenUsed block="button right" weight=94 fixedInstance //% whenUsed block="brick button right" weight=94 fixedInstance
export const buttonRight: Button = new DevButton(DAL.BUTTON_ID_RIGHT) export const buttonRight: Button = new DevButton(DAL.BUTTON_ID_RIGHT)
/** /**
* Up button. * Up button on the EV3 Brick.
*/ */
//% whenUsed block="button up" weight=95 fixedInstance //% whenUsed block="brick button up" weight=95 fixedInstance
export const buttonUp: Button = new DevButton(DAL.BUTTON_ID_UP) export const buttonUp: Button = new DevButton(DAL.BUTTON_ID_UP)
/** /**
* Down button. * Down button on the EV3 Brick.
*/ */
//% whenUsed block="button down" weight=95 fixedInstance //% whenUsed block="brick button down" weight=95 fixedInstance
export const buttonDown: Button = new DevButton(DAL.BUTTON_ID_DOWN) export const buttonDown: Button = new DevButton(DAL.BUTTON_ID_DOWN)
/**
* Enter button.
*/
//% whenUsed block="button enter" weight=95 fixedInstance
export const buttonEnter: Button = new DevButton(DAL.BUTTON_ID_ENTER)
} }
@ -241,8 +234,8 @@ namespace output {
* @param pattern the lights pattern to use. * @param pattern the lights pattern to use.
*/ */
//% blockId=setLights block="set status light %pattern=led_pattern" //% blockId=setLights block="set status light %pattern=led_pattern"
//% weight=100 group="Lights" //% weight=100 group="Brick"
export function setLights(pattern: number): void { export function setStatusLight(pattern: number): void {
if (currPattern === pattern) if (currPattern === pattern)
return return
currPattern = pattern currPattern = pattern
@ -259,7 +252,7 @@ namespace output {
//% blockId=led_pattern block="%pattern" //% blockId=led_pattern block="%pattern"
//% shim=TD_ID colorSecondary="#6e9a36" //% shim=TD_ID colorSecondary="#6e9a36"
//% blockHidden=true useEnumVal=1 pattern.fieldOptions.decompileLiterals=1 //% blockHidden=true useEnumVal=1 pattern.fieldOptions.decompileLiterals=1
export function getPattern(pattern: LightsPattern): number { export function pattern(pattern: LightsPattern): number {
return pattern; return pattern;
} }
} }

View File

@ -9,21 +9,30 @@ const enum ColorSensorMode {
} }
const enum ColorSensorColor { const enum ColorSensorColor {
//% block="none"
None, None,
//% block="black"
Black, Black,
//% block="blue"
Blue, Blue,
//% block="green"
Green, Green,
//% block="yellow"
Yellow, Yellow,
//% block="red"
Red, Red,
//% block="white"
White, White,
//% block="brown"
Brown, Brown,
} }
namespace input { namespace input {
//% fixedInstances
export class ColorSensor extends internal.UartSensor { export class ColorSensor extends internal.UartSensor {
constructor() { constructor(port: number) {
super() super(port)
} }
_deviceType() { _deviceType() {
@ -34,22 +43,93 @@ namespace input {
this._setMode(m) this._setMode(m)
} }
getAmbientLight() { _query() {
if (this.mode == ColorSensorMode.Color)
return this.getNumber(NumberFormat.UInt8LE, 0)
return 0
}
_update(prev: number, curr: number) {
control.raiseEvent(this._id, curr);
}
/**
* Registers code to run when the given color is detected
* @param color the color to dtect
* @param handler the code to run when detected
*/
//% help=input/color/on-color-detected
//% block="on %sensor|detected %color"
//% blockId=colorOnColorDetected
//% parts="colorsensor"
//% blockNamespace=input
//% weight=100 blockGap=8
//% group="Color Sensor"
onColorDetected(color: ColorSensorColor, handler: () => void) {
control.onEvent(this._id, <number>color, handler);
this.setMode(ColorSensorMode.Color)
if (this.color() == color)
control.runInBackground(handler)
}
/**
* Get current ambient light value from the color sensor.
* @param color the color sensor to query the request
*/
//% help=input/color/ambient-light
//% block="%color| ambient light"
//% blockId=colorGetAmbient
//% parts="colorsensor"
//% blockNamespace=input
//% weight=65 blockGap=8
//% group="Color Sensor"
ambientLight() {
this.setMode(ColorSensorMode.Ambient) this.setMode(ColorSensorMode.Ambient)
return this.getNumber(NumberFormat.UInt8LE, 0) return this.getNumber(NumberFormat.UInt8LE, 0)
} }
getReflectedLight() { /**
* Get current reflected light value from the color sensor.
* @param color the color sensor to query the request
*/
//% help=input/color/refelected-light
//% block="%color| reflected light"
//% blockId=colorGetReflected
//% parts="colorsensor"
//% blockNamespace=input
//% weight=64 blockGap=8
//% group="Color Sensor"
reflectedLight(): number {
this.setMode(ColorSensorMode.Reflect) this.setMode(ColorSensorMode.Reflect)
return this.getNumber(NumberFormat.UInt8LE, 0) return this.getNumber(NumberFormat.UInt8LE, 0)
} }
getColor(): ColorSensorColor { /**
* Get the current color from the color sensor.
* @param color the color sensor to query the request
*/
//% help=input/color/color
//% block="%color| color"
//% blockId=colorGetColor
//% parts="colorsensor"
//% blockNamespace=input
//% weight=66 blockGap=8
//% group="Color Sensor"
color(): ColorSensorColor {
this.setMode(ColorSensorMode.Color) this.setMode(ColorSensorMode.Color)
return this.getNumber(NumberFormat.UInt8LE, 0) return this.getNumber(NumberFormat.UInt8LE, 0)
} }
} }
//% whenUsed //% whenUsed block="color sensor 3" weight=95 fixedInstance
export const color: ColorSensor = new ColorSensor() export const color3: ColorSensor = new ColorSensor(3)
//% whenUsed block="color sensor 1" weight=95 fixedInstance
export const color1: ColorSensor = new ColorSensor(1)
//% whenUsed block="color sensor 2" weight=95 fixedInstance
export const color2: ColorSensor = new ColorSensor(2)
//% whenUsed block="color sensor 4" weight=95 fixedInstance
export const color4: ColorSensor = new ColorSensor(4)
} }

View File

@ -5,9 +5,10 @@ const enum GyroSensorMode {
} }
namespace input { namespace input {
//% fixedInstances
export class GyroSensor extends internal.UartSensor { export class GyroSensor extends internal.UartSensor {
constructor() { constructor(port: number) {
super() super(port)
} }
_deviceType() { _deviceType() {
@ -18,17 +19,48 @@ namespace input {
this._setMode(m) this._setMode(m)
} }
getAngle() { /**
* Get the current angle from the gyroscope.
* @param sensor the gyroscope to query the request
*/
//% help=input/gyro/angle
//% block="%sensor|angle"
//% blockId=gyroGetAngle
//% parts="gyroscope"
//% blockNamespace=input
//% weight=65 blockGap=8
//% group="Gyro Sensor"
angle() {
this.setMode(GyroSensorMode.Angle) this.setMode(GyroSensorMode.Angle)
return this.getNumber(NumberFormat.Int16LE, 0) return this.getNumber(NumberFormat.Int16LE, 0)
} }
getRate() { /**
* Get the current rotation rate from the gyroscope.
* @param sensor the gyroscope to query the request
*/
//% help=input/gyro/rate
//% block="%sensor|rotation rate"
//% blockId=gyroGetRate
//% parts="gyroscope"
//% blockNamespace=input
//% weight=65 blockGap=8
//% group="Gyro Sensor"
rate() {
this.setMode(GyroSensorMode.Rate) this.setMode(GyroSensorMode.Rate)
return this.getNumber(NumberFormat.Int16LE, 0) return this.getNumber(NumberFormat.Int16LE, 0)
} }
} }
//% whenUsed //% fixedInstance whenUsed block="gyro sensor 2"
export const gyro: GyroSensor = new GyroSensor() export const gyro2: GyroSensor = new GyroSensor(2)
//% fixedInstance whenUsed block="gyro sensor 1"
export const gyro1: GyroSensor = new GyroSensor(1)
//% fixedInstance whenUsed block="gyro sensor 3"
export const gyro3: GyroSensor = new GyroSensor(3)
//% fixedInstance whenUsed block="gyro sensor 4"
export const gyro4: GyroSensor = new GyroSensor(4)
} }

View File

@ -27,30 +27,27 @@ namespace input.internal {
let analogMM: MMap let analogMM: MMap
let uartMM: MMap let uartMM: MMap
let devcon: Buffer let devcon: Buffer
let sensors: SensorInfo[] let sensorInfos: SensorInfo[]
let autoSensors: Sensor[]
class SensorInfo { class SensorInfo {
port: number port: number
sensor: Sensor sensor: Sensor
sensors: Sensor[]
connType: number connType: number
devType: number devType: number
manual: boolean
constructor(p: number) { constructor(p: number) {
this.port = p this.port = p
this.connType = DAL.CONN_NONE this.connType = DAL.CONN_NONE
this.devType = DAL.DEVICE_TYPE_NONE this.devType = DAL.DEVICE_TYPE_NONE
this.sensor = null this.sensors = []
this.manual = false
} }
} }
function init() { function init() {
if (sensors) return if (sensorInfos) return
sensors = [] sensorInfos = []
for (let i = 0; i < DAL.NUM_INPUTS; ++i) sensors.push(new SensorInfo(i)) for (let i = 0; i < DAL.NUM_INPUTS; ++i) sensorInfos.push(new SensorInfo(i))
autoSensors = []
devcon = output.createBuffer(DevConOff.Size) devcon = output.createBuffer(DevConOff.Size)
analogMM = control.mmap("/dev/lms_analog", AnalogOff.Size, 0) analogMM = control.mmap("/dev/lms_analog", AnalogOff.Size, 0)
@ -64,7 +61,7 @@ namespace input.internal {
loops.pause(500) loops.pause(500)
}) })
for (let info_ of sensors) { for (let info_ of sensorInfos) {
let info = info_ let info = info_
unsafePollForChanges(50, () => { unsafePollForChanges(50, () => {
if (info.sensor) return info.sensor._query() if (info.sensor) return info.sensor._query()
@ -90,7 +87,7 @@ namespace input.internal {
let conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS) let conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
let numChanged = 0 let numChanged = 0
for (let info of sensors) { for (let info of sensorInfos) {
let newConn = conns[info.port] let newConn = conns[info.port]
if (newConn == info.connType) if (newConn == info.connType)
continue continue
@ -117,77 +114,44 @@ namespace input.internal {
if (numChanged == 0) if (numChanged == 0)
return return
let autos = sensors.filter(s => !s.manual) for (let si of sensorInfos) {
if (si.sensor && si.sensor._deviceType() != si.devType) {
// first free up disconnected sensors si.sensor = null
for (let info of autos) { }
if (info.sensor && info.devType == DAL.DEVICE_TYPE_NONE) if (si.devType != DAL.DEVICE_TYPE_NONE) {
info.sensor._setPort(0) // TODO figure out compiler problem when '|| null' is added here!
} si.sensor = si.sensors.filter(s => s._deviceType() == si.devType)[0]
if (si.sensor == null) {
for (let info of autos) { control.dmesg(`sensor not found for type=${si.devType} at ${si.port}`)
if (!info.sensor && info.devType != DAL.DEVICE_TYPE_NONE) { } else {
let found = false control.dmesg(`sensor connected type=${si.devType} at ${si.port}`)
for (let s of autoSensors) { si.sensor._activated()
if (s.getPort() == 0 && s._deviceType() == info.devType) {
s._setPort(info.port + 1)
found = true
break
}
} }
if (!found)
control.dmesg(`sensor not found for type=${info.devType} at ${info.port}`)
} }
} }
} }
export class Sensor extends control.Component { export class Sensor extends control.Component {
protected port: number protected port: number // this is 0-based
constructor() { constructor(port_: number) {
super() super()
if (!(1 <= port_ && port_ <= DAL.NUM_INPUTS))
control.panic(120)
this.port = port_ - 1
init() init()
this.port = -1 sensorInfos[this.port].sensors.push(this)
let tp = this._deviceType()
if (autoSensors.filter(s => s._deviceType() == tp).length == 0) {
autoSensors.push(this)
}
} }
// 0 - disable, 1-4 port number _activated() { }
_setPort(port: number, manual = false) {
port = Math.clamp(0, 4, port | 0) - 1;
if (port == this.port) return
this.port = port
control.dmesg(`sensor set port ${port} on devtype=${this._deviceType()}`)
for (let i = 0; i < sensors.length; ++i) {
if (i != this.port && sensors[i].sensor == this) {
sensors[i].sensor = null
sensors[i].manual = false
}
}
if (this.port >= 0) {
let prev = sensors[this.port].sensor
if (prev && prev != this)
prev._setPort(0)
sensors[this.port].sensor = this
sensors[this.port].manual = manual
}
this._portUpdated()
}
protected _portUpdated() { }
setPort(port: number) {
this._setPort(port, true)
}
// 1-based
getPort() { getPort() {
return this.port + 1 return this.port + 1
} }
isManual() { isActive() {
return this.port >= 0 && sensors[this.port].manual return sensorInfos[this.port].sensor == this
} }
_query() { _query() {
@ -203,12 +167,12 @@ namespace input.internal {
} }
export class AnalogSensor extends Sensor { export class AnalogSensor extends Sensor {
constructor() { constructor(port: number) {
super() super(port)
} }
_readPin6() { _readPin6() {
if (this.port < 0) return 0 if (!this.isActive()) return 0
return analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.InPin6 + 2 * this.port) return analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.InPin6 + 2 * this.port)
} }
} }
@ -216,32 +180,26 @@ namespace input.internal {
export class UartSensor extends Sensor { export class UartSensor extends Sensor {
protected mode: number protected mode: number // the mode user asked for
protected realmode: number protected realmode: number // the mode the hardware is in
constructor() { constructor(port: number) {
super() super(port)
this.mode = 0 this.mode = 0
this.realmode = -1 this.realmode = -1
} }
protected _portUpdated() { _activated() {
this.realmode = -1 this.realmode = 0
if (this.port >= 0) { // uartReset(this.port) // TODO is it ever needed?
if (this.isManual()) { this._setMode(this.mode)
uartReset(this.port)
} else {
this.realmode = 0
}
this._setMode(this.mode)
}
} }
protected _setMode(m: number) { protected _setMode(m: number) {
//control.dmesg(`_setMode p=${this.port} m: ${this.realmode} -> ${m}`) //control.dmesg(`_setMode p=${this.port} m: ${this.realmode} -> ${m}`)
let v = m | 0 let v = m | 0
this.mode = v this.mode = v
if (this.port < 0) return if (!this.isActive()) return
if (this.realmode != this.mode) { if (this.realmode != this.mode) {
this.realmode = v this.realmode = v
setUartMode(this.port, v) setUartMode(this.port, v)
@ -249,10 +207,12 @@ namespace input.internal {
} }
getBytes(): Buffer { getBytes(): Buffer {
return getUartBytes(this.port) return getUartBytes(this.isActive() ? this.port : -1)
} }
getNumber(fmt: NumberFormat, off: number) { getNumber(fmt: NumberFormat, off: number) {
if (!this.isActive())
return 0
return getUartNumber(fmt, off, this.port) return getUartNumber(fmt, off, this.port)
} }
} }

View File

@ -40,41 +40,130 @@ namespace input {
} }
} }
export class IrSensor extends internal.UartSensor { let buttons: RemoteInfraredBeaconButton[]
private channel: IrRemoteChannel
private buttons: Button[];
constructor() { function create(ir: InfraredSensor) {
super() // it's created by referencing it
this.channel = IrRemoteChannel.Ch0 }
this.buttons = []
// otherwise button events won't work export function irButton(id: IrRemoteButton): RemoteInfraredBeaconButton {
this.mode = IrSensorMode.RemoteControl if (buttons == null) {
buttons = []
for (let i = 0; i < 5; ++i) { for (let i = 0; i < 5; ++i) {
this.buttons.push(new Button()) buttons.push(new RemoteInfraredBeaconButton(new Button()))
} }
// make sure sensors are up
create(infraredSensor1)
create(infraredSensor2)
create(infraredSensor3)
create(infraredSensor4)
} }
button(id: IrRemoteButton) { let num = -1
let num = -1 while (id) {
while (id) { id >>= 1;
id >>= 1; num++;
num++; }
} num = Math.clamp(0, buttons.length - 1, num)
num = Math.clamp(0, this.buttons.length - 1, num) return buttons[num]
return this.buttons[num] }
//% fixedInstances
export class RemoteInfraredBeaconButton extends control.Component {
private button: Button;
constructor(button: Button) {
super();
this.button = button;
}
_update(curr: boolean) {
this.button._update(curr);
}
/**
* Check if a remote button is currently pressed or not.
* @param button the remote button to query the request
*/
//% help=input/remote-infrared-beacon/is-pressed
//% block="%button|is pressed"
//% blockId=remoteButtonIsPressed
//% parts="remote"
//% blockNamespace=input
//% weight=81 blockGap=8
//% group="Remote Infrared Beacon"
isPressed() {
return this.button.isPressed();
}
/**
* See if the remote button was pressed again since the last time you checked.
* @param button the remote button to query the request
*/
//% help=input/remote-infrared-beacon/was-pressed
//% block="%button|was pressed"
//% blockId=remotebuttonWasPressed
//% parts="remote"
//% blockNamespace=input
//% weight=80 blockGap=8
//% group="Remote Infrared Beacon"
wasPressed() {
return this.button.wasPressed();
}
/**
* Do something when a button or sensor is clicked, up or down
* @param button the button that needs to be clicked or used
* @param event the kind of button gesture that needs to be detected
* @param body code to run when the event is raised
*/
//% help=input/remote-infrared-beacon/on-event
//% blockId=remotebuttonEvent block="on %button|%event"
//% parts="remote"
//% blockNamespace=input
//% weight=99 blockGap=8
//% group="Remote Infrared Beacon"
onEvent(ev: ButtonEvent, body: () => void) {
this.button.onEvent(ev, body);
}
}
//% fixedInstances
export class InfraredSensor extends internal.UartSensor {
private channel: IrRemoteChannel;
private proximityThreshold: number;
constructor(port: number) {
super(port)
this.channel = IrRemoteChannel.Ch0
this.proximityThreshold = 10;
irButton(0) // make sure buttons array is initalized
// and set the mode, as otherwise button events won't work
this.mode = IrSensorMode.RemoteControl;
} }
_query() { _query() {
if (this.mode == IrSensorMode.RemoteControl) if (this.mode == IrSensorMode.RemoteControl)
return mapButton(this.getNumber(NumberFormat.UInt8LE, this.channel)) return mapButton(this.getNumber(NumberFormat.UInt8LE, this.channel));
else if (this.mode == IrSensorMode.Proximity) {
const d = this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff;
return d < this.proximityThreshold ? PromixityEvent.ObjectNear
: d > this.proximityThreshold + 5 ? PromixityEvent.ObjectDetected
: 0;
}
return 0 return 0
} }
_update(prev: number, curr: number) { _update(prev: number, curr: number) {
for (let i = 0; i < this.buttons.length; ++i) { if (this.mode == IrSensorMode.RemoteControl) {
let v = !!(curr & (1 << i)) for (let i = 0; i < buttons.length; ++i) {
this.buttons[i].update(v) let v = !!(curr & (1 << i))
buttons[i]._update(v)
}
} else {
if (curr)
control.raiseEvent(this._id, curr);
} }
} }
@ -85,59 +174,113 @@ namespace input {
setRemoteChannel(c: IrRemoteChannel) { setRemoteChannel(c: IrRemoteChannel) {
c = Math.clamp(0, 3, c | 0) c = Math.clamp(0, 3, c | 0)
this.channel = c this.channel = c
this.setMode(IrSensorMode.RemoteControl) this._setMode(IrSensorMode.RemoteControl)
} }
setMode(m: IrSensorMode) { setMode(m: IrSensorMode) {
this._setMode(m) this._setMode(m)
} }
getDistance() { /**
this.setMode(IrSensorMode.Proximity) * Registers code to run when an object is getting near.
* @param handler the code to run when detected
*/
//% help=input/infrared/on-object-near
//% block="on %sensor|object near"
//% blockId=infraredOnObjectNear
//% parts="infraredsensor"
//% blockNamespace=input
//% weight=100 blockGap=8
//% group="Infrared Sensor"
onObjectNear(handler: () => void) {
control.onEvent(this._id, PromixityEvent.ObjectNear, handler);
if (this.proximity() == PromixityEvent.ObjectNear)
control.runInBackground(handler);
}
setObjectNearThreshold(distance: number) {
this.proximityThreshold = Math.max(1, Math.min(95, distance));
}
/**
* Get the promixity measured by the infrared sensor, from ``0`` (close) to ``100`` (far)
* @param ir the infrared sensor
*/
//% help=input/infrared/proximity
//% block="%infrared|proximity"
//% blockId=infraredGetProximity
//% parts="infrared"
//% blockNamespace=input
//% weight=65 blockGap=8
//% group="Infrared Sensor"
proximity() {
this._setMode(IrSensorMode.Proximity)
return this.getNumber(NumberFormat.UInt8LE, 0) return this.getNumber(NumberFormat.UInt8LE, 0)
} }
getRemoteCommand() { /**
this.setMode(IrSensorMode.RemoteControl) * Get the remote commandreceived the infrared sensor.
* @param ir the infrared sensor
*/
//% help=input/infrared/remote-command
//% block="%infrared|remote command"
//% blockId=infraredGetRemoteCommand
//% parts="infrared"
//% blockNamespace=input
//% weight=65 blockGap=8
//% group="Infrared Sensor"
remoteCommand() {
this._setMode(IrSensorMode.RemoteControl)
return this.getNumber(NumberFormat.UInt8LE, this.channel) return this.getNumber(NumberFormat.UInt8LE, this.channel)
} }
// TODO
getDirectionAndDistance() { getDirectionAndDistance() {
this.setMode(IrSensorMode.Seek) this._setMode(IrSensorMode.Seek)
return this.getNumber(NumberFormat.UInt16LE, this.channel * 2) return this.getNumber(NumberFormat.UInt16LE, this.channel * 2)
} }
} }
//% whenUsed //% fixedInstance whenUsed block="infrared sensor 1"
export const ir: IrSensor = new IrSensor() export const infraredSensor1: InfraredSensor = new InfraredSensor(1)
/** //% fixedInstance whenUsed block="infrared sensor 2"
* Remote top-left button. export const infraredSensor2: InfraredSensor = new InfraredSensor(2)
*/
//% whenUsed block="remote top-left" weight=95 fixedInstance
export const remoteTopLeft = ir.button(IrRemoteButton.TopLeft)
/** //% fixedInstance whenUsed block="infrared sensor 3"
* Remote top-right button. export const infraredSensor3: InfraredSensor = new InfraredSensor(3)
*/
//% whenUsed block="remote top-right" weight=95 fixedInstance
export const remoteTopRight = ir.button(IrRemoteButton.TopRight)
/** //% fixedInstance whenUsed block="infrared sensor 4"
* Remote bottom-left button. export const infraredSensor4: InfraredSensor = new InfraredSensor(4)
*/
//% whenUsed block="remote bottom-left" weight=95 fixedInstance
export const remoteBottomLeft = ir.button(IrRemoteButton.BottomLeft)
/**
* Remote bottom-right button.
*/
//% whenUsed block="remote bottom-right" weight=95 fixedInstance
export const remoteBottomRight = ir.button(IrRemoteButton.BottomRight)
/** /**
* Remote beacon (center) button. * Remote beacon (center) button.
*/ */
//% whenUsed block="remote center" weight=95 fixedInstance //% whenUsed block="remote button center" weight=95 fixedInstance
export const remoteCenter = ir.button(IrRemoteButton.CenterBeacon) export const remoteButtonCenter = irButton(IrRemoteButton.CenterBeacon)
/**
* Remote top-left button.
*/
//% whenUsed block="remote button top-left" weight=95 fixedInstance
export const remoteButtonTopLeft = irButton(IrRemoteButton.TopLeft)
/**
* Remote top-right button.
*/
//% whenUsed block="remote button top-right" weight=95 fixedInstance
export const remoteButtonTopRight = irButton(IrRemoteButton.TopRight)
/**
* Remote bottom-left button.
*/
//% whenUsed block="remote button bottom-left" weight=95 fixedInstance
export const remoteButtonBottomLeft = irButton(IrRemoteButton.BottomLeft)
/**
* Remote bottom-right button.
*/
//% whenUsed block="remote button bottom-right" weight=95 fixedInstance
export const remoteButtonBottomRight = irButton(IrRemoteButton.BottomRight)
} }

View File

@ -1,4 +1,5 @@
//% color="#B4009E" weight=98 icon="\uf192" //% color="#B4009E" weight=98 icon="\uf192"
//% groups='["Brick", "Touch Sensor", "Color Sensor", "Ultrasonic Sensor", "Infrared Sensor", "Remote Infrared Beacon", "Gyro Sensor"]'
namespace input { namespace input {
} }

View File

@ -1,8 +1,13 @@
enum Output { enum Output {
//% block="A"
A = 0x01, A = 0x01,
//% block="B"
B = 0x02, B = 0x02,
//% block="C"
C = 0x04, C = 0x04,
//% block="D"
D = 0x08, D = 0x08,
//% block="All"
ALL = 0x0f ALL = 0x0f
} }
@ -15,7 +20,6 @@ enum OutputType {
namespace output { namespace output {
let pwmMM: MMap let pwmMM: MMap
let motorMM: MMap let motorMM: MMap
let currentSpeed: number[] = []
const enum MotorDataOff { const enum MotorDataOff {
TachoCounts = 0, // int32 TachoCounts = 0, // int32
@ -31,13 +35,7 @@ namespace output {
if (!pwmMM) control.fail("no PWM file") if (!pwmMM) control.fail("no PWM file")
motorMM = control.mmap("/dev/lms_motor", MotorDataOff.Size * DAL.NUM_OUTPUTS, 0) motorMM = control.mmap("/dev/lms_motor", MotorDataOff.Size * DAL.NUM_OUTPUTS, 0)
stop(Output.ALL) resetMotors()
currentSpeed[Output.A] = -1;
currentSpeed[Output.B] = -1;
currentSpeed[Output.C] = -1;
currentSpeed[Output.D] = -1;
currentSpeed[Output.ALL] = -1;
let buf = output.createBuffer(1) let buf = output.createBuffer(1)
buf[0] = DAL.opProgramStart buf[0] = DAL.opProgramStart
@ -55,69 +53,173 @@ namespace output {
} }
function mkCmd(out: Output, cmd: number, addSize: number) { function mkCmd(out: Output, cmd: number, addSize: number) {
let b = createBuffer(2 + addSize) const b = createBuffer(2 + addSize)
b.setNumber(NumberFormat.UInt8LE, 0, cmd) b.setNumber(NumberFormat.UInt8LE, 0, cmd)
b.setNumber(NumberFormat.UInt8LE, 1, out) b.setNumber(NumberFormat.UInt8LE, 1, out)
return b return b
} }
/** function resetMotors() {
* Turn a motor on for a specified number of milliseconds. reset(Output.ALL)
* @param out the output connection that the motor is connected to
* @param ms the number of milliseconds to turn the motor on, eg: 500
* @param useBrake whether or not to use the brake, defaults to false
*/
//% blockId=output_turn block="turn motor %out| on for %ms|milliseconds"
//% weight=100 group="Motors"
export function turn(out: Output, ms: number, useBrake = false) {
// TODO: use current power / speed configuration
output.step(out, {
speed: 100,
step1: 0,
step2: ms,
step3: 0,
useSteps: false,
useBrake: useBrake
})
} }
/** /**
* Turn motor off. * Stops all motors
* @param out the output connection that the motor is connected to
*/ */
//% blockId=output_stop block="turn motor %out|off" //% blockId=motorStopAll block="stop all motors"
//% weight=90 group="Motors" //% weight=10 group="Motors" blockGap=8
export function stop(out: Output, useBrake = false) { export function stopAllMotors() {
let b = mkCmd(out, DAL.opOutputStop, 1) const b = mkCmd(Output.ALL, DAL.opOutputStop, 0)
b.setNumber(NumberFormat.UInt8LE, 2, useBrake ? 1 : 0)
writePWM(b) writePWM(b)
} }
/** //% fixedInstances
* Turn motor on. export class Motor extends control.Component {
* @param out the output connection that the motor is connected to private port: Output;
*/ private large: boolean;
//% blockId=output_start block="turn motor %out|on" private brake: boolean;
//% weight=95 group="Motors"
export function start(out: Output) {
if (currentSpeed[out] == -1) setSpeed(out, 50)
let b = mkCmd(out, DAL.opOutputStart, 0)
writePWM(b)
}
export function reset(out: Output) { constructor(port: Output, large: boolean) {
let b = mkCmd(out, DAL.opOutputReset, 0) super();
writePWM(b) this.port = port;
} this.large = large;
this.brake = false;
}
export function clearCount(out: Output) { /**
let b = mkCmd(out, DAL.opOutputClearCount, 0) * Power on or off the motor.
writePWM(b) * @param motor the motor to turn on
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) { * @param power the motor power level from ``-100`` to ``100``, eg: 50
if (out & (1 << i)) { */
motorMM.setNumber(NumberFormat.Int32LE, i * MotorDataOff.Size + MotorDataOff.TachoSensor, 0) //% blockId=outputMotorOn block="%motor|%onOrOff"
//% onOrOff.fieldEditor=toggleonoff
//% weight=99 group="Motors" blockGap=8
on(onOrOff: boolean = true) {
if (onOrOff) {
const b = mkCmd(this.port, DAL.opOutputStart, 0)
writePWM(b);
} else {
const b = mkCmd(this.port, DAL.opOutputStop, 1)
b.setNumber(NumberFormat.UInt8LE, 2, this.brake ? 1 : 0)
writePWM(b)
} }
} }
/**
* Sets the motor power level from ``-100`` to ``100``.
* @param motor the output connection that the motor is connected to
* @param power the desired speed to use. eg: 50
*/
//% blockId=motorSetPower block="%motor|set power to %speed"
//% weight=62 group="Motors" blockGap=8
//% speed.min=-100 speed.max=100
setPower(power: number) {
const b = mkCmd(this.port, DAL.opOutputPower, 1)
b.setNumber(NumberFormat.Int8LE, 2, Math.clamp(-100, 100, power))
writePWM(b)
}
/**
* Sets the automatic brake on or off when the motor is off
* @param brake a value indicating if the motor should break when off
*/
//% blockId=outputMotorSetBrakeMode block="%motor|set brake %brake"
//% brake.fieldEditor=toggleonoff
//% weight=60 group="Motors" blockGap=8
setBrake(brake: boolean) {
this.brake = brake;
}
/**
* Reverses the motor polarity
*/
//% blockId=motorSetReversed block="%motor|set reversed %reversed"
//% reversed.fieldEditor=toggleonoff
//% weight=59 group="Motors"
setReversed(reversed: boolean) {
const b = mkCmd(this.port, DAL.opOutputPolarity, 1)
b.setNumber(NumberFormat.Int8LE, 2, reversed ? -1 : 1);
writePWM(b)
}
/**
* Gets motor actual speed.
* @param motor the port which connects to the motor
*/
//% blockId=motorSpeed block="%motor|speed"
//% weight=50 group="Motors" blockGap=8
speed(): number {
return getMotorData(this.port).actualSpeed;
}
/**
* Gets motor step count.
* @param motor the port which connects to the motor
*/
//% blockId=motorCount block="%motor|count"
//% weight=49 group="Motors" blockGap=8
count(): number {
return getMotorData(this.port).count;
}
/**
* Gets motor tacho count.
* @param motor the port which connects to the motor
*/
//% blockId=motorTachoCount block="%motor|tacho count"
//% weight=48 group="Motors"
tachoCount(): number {
return getMotorData(this.port).tachoCount;
}
/**
* Clears the motor count
*/
clearCount() {
const b = mkCmd(this.port, DAL.opOutputClearCount, 0)
writePWM(b)
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
if (this.port & (1 << i)) {
motorMM.setNumber(NumberFormat.Int32LE, i * MotorDataOff.Size + MotorDataOff.TachoSensor, 0)
}
}
}
/**
* Resets the motor.
*/
reset() {
reset(this.port);
}
}
//% whenUsed fixedInstance block="large motor A"
export const largeMotorA = new Motor(Output.A, true);
//% whenUsed fixedInstance block="large motor B"
export const largeMotorB = new Motor(Output.B, true);
//% whenUsed fixedInstance block="large motor C"
export const largeMotorC = new Motor(Output.C, true);
//% whenUsed fixedInstance block="large motor D"
export const largeMotorD = new Motor(Output.D, true);
//% whenUsed fixedInstance block="medium motor A"
export const mediumMotorA = new Motor(Output.A, false);
//% whenUsed fixedInstance block="medium motor B"
export const mediumMotorB = new Motor(Output.B, false);
//% whenUsed fixedInstance block="medium motor C"
export const mediumMotorC = new Motor(Output.C, false);
//% whenUsed fixedInstance block="medium motor D"
export const mediumMotorD = new Motor(Output.D, false);
function reset(out: Output) {
let b = mkCmd(out, DAL.opOutputReset, 0)
writePWM(b)
} }
function outOffset(out: Output) { function outOffset(out: Output) {
@ -128,14 +230,14 @@ namespace output {
return 0 return 0
} }
export interface MotorData { interface MotorData {
actualSpeed: number; // -100..+100 actualSpeed: number; // -100..+100
tachoCount: number; tachoCount: number;
count: number; count: number;
} }
// only a single output at a time // only a single output at a time
export function getMotorData(out: Output): MotorData { function getMotorData(out: Output): MotorData {
let buf = motorMM.slice(outOffset(out), MotorDataOff.Size) let buf = motorMM.slice(outOffset(out), MotorDataOff.Size)
return { return {
actualSpeed: buf.getNumber(NumberFormat.Int8LE, MotorDataOff.Speed), actualSpeed: buf.getNumber(NumberFormat.Int8LE, MotorDataOff.Speed),
@ -144,52 +246,7 @@ namespace output {
} }
} }
/** interface StepOptions {
* Get motor speed.
* @param out the output connection that the motor is connected to
*/
//% blockId=output_getCurrentSpeed block="motor %out|speed"
//% weight=70 group="Motors"
export function getCurrentSpeed(out: Output) {
return getMotorData(out).actualSpeed;
}
/**
* Set motor speed.
* @param out the output connection that the motor is connected to
* @param speed the desired speed to use. eg: 100
*/
//% blockId=output_setSpeed block="set motor %out| speed to %speed"
//% weight=81 group="Motors"
//% speed.min=-100 speed.max=100
export function setSpeed(out: Output, speed: number) {
currentSpeed[out] = speed;
let b = mkCmd(out, DAL.opOutputSpeed, 1)
b.setNumber(NumberFormat.Int8LE, 2, Math.clamp(-100, 100, speed))
writePWM(b)
}
/**
* Set motor power.
* @param out the output connection that the motor is connected to
* @param power the desired power to use. eg: 100
*/
//% blockId=output_setPower block="set motor %out| power to %power"
//% weight=80 group="Motors"
//% power.min=-100 power.max=100
export function setPower(out: Output, power: number) {
let b = mkCmd(out, DAL.opOutputPower, 1)
b.setNumber(NumberFormat.Int8LE, 2, Math.clamp(-100, 100, power))
writePWM(b)
}
export function setPolarity(out: Output, polarity: number) {
let b = mkCmd(out, DAL.opOutputPolarity, 1)
b.setNumber(NumberFormat.Int8LE, 2, Math.clamp(-1, 1, polarity))
writePWM(b)
}
export interface StepOptions {
power?: number; power?: number;
speed?: number; // either speed or power has to be present speed?: number; // either speed or power has to be present
step1: number; step1: number;
@ -199,7 +256,7 @@ namespace output {
useBrake?: boolean; useBrake?: boolean;
} }
export function step(out: Output, opts: StepOptions) { function step(out: Output, opts: StepOptions) {
let op = opts.useSteps ? DAL.opOutputStepSpeed : DAL.opOutputTimeSpeed let op = opts.useSteps ? DAL.opOutputStepSpeed : DAL.opOutputTimeSpeed
let speed = opts.speed let speed = opts.speed
if (speed == null) { if (speed == null) {

View File

@ -78,13 +78,21 @@ namespace screen {
} }
} }
export function setPixel(x: number, y: number, mode = Draw.Normal) { /**
* Sets a pixel on or off
* @param on a value indicating if the pixel should be on or off
* @param x the starting position's x coordinate, eg: 0
* @param y the starting position's x coordinate, eg: 0
*/
//% blockId=screen_setpixel block="set pixel %on| at x: %x| y: %y"
//% weight=98 group="Brick" blockNamespace=output
//% x.min=0 x.max=178 y.min=0 y.max=128 on.fieldEditor=toggleonoff
export function setPixel(on: boolean, x: number, y: number) {
x |= 0 x |= 0
y |= 0 y |= 0
if (0 <= x && x < DAL.LCD_WIDTH && 0 <= y && y < DAL.LCD_HEIGHT) if (0 <= x && x < DAL.LCD_WIDTH && 0 <= y && y < DAL.LCD_HEIGHT)
_setPixel(x, y, mode) _setPixel(x, y, on ? Draw.Normal : Draw.Clear)
} }
/** /**
* Show text on the screen. * Show text on the screen.
@ -92,10 +100,10 @@ namespace screen {
* @param x the starting position's x coordinate, eg: 0 * @param x the starting position's x coordinate, eg: 0
* @param y the starting position's x coordinate, eg: 0 * @param y the starting position's x coordinate, eg: 0
*/ */
//% blockId=screen_drawText block="print %text| at x: %x| y: %y" //% blockId=screen_print block="print %text| at x: %x| y: %y"
//% weight=99 group="Screen" blockNamespace=output inlineInputMode="inline" //% weight=99 group="Brick" blockNamespace=output inlineInputMode="inline"
//% x.min=0 x.max=178 y.min=0 y.max=128 //% x.min=0 x.max=178 y.min=0 y.max=128
export function drawText(text: string, x: number, y: number, mode = Draw.Normal) { export function print(text: string, x: number, y: number, mode = Draw.Normal) {
x |= 0 x |= 0
y |= 0 y |= 0
if (!currFont) currFont = defaultFont() if (!currFont) currFont = defaultFont()

View File

@ -1,8 +1,8 @@
screen.clear() screen.clear()
screen.drawText("PXT!", 10, 30, Draw.Quad) screen.print("PXT!", 10, 30, Draw.Quad)
screen.drawRect(40, 40, 20, 10, Draw.Fill) screen.drawRect(40, 40, 20, 10, Draw.Fill)
output.setLights(LightsPattern.Orange) output.setStatusLight(LightsPattern.Orange)
screen.drawIcon(100, 50, screen.doubleIcon(screen.heart), Draw.Double | Draw.Transparent) screen.drawIcon(100, 50, screen.doubleIcon(screen.heart), Draw.Double | Draw.Transparent)
@ -12,37 +12,37 @@ input.buttonEnter.onEvent(ButtonEvent.Click, () => {
input.buttonLeft.onEvent(ButtonEvent.Click, () => { input.buttonLeft.onEvent(ButtonEvent.Click, () => {
screen.drawRect(10, 70, 20, 10, Draw.Fill) screen.drawRect(10, 70, 20, 10, Draw.Fill)
output.setLights(LightsPattern.Red) output.setStatusLight(LightsPattern.Red)
screen.setFont(screen.microbitFont()) screen.setFont(screen.microbitFont())
}) })
input.buttonRight.onEvent(ButtonEvent.Click, () => { input.buttonRight.onEvent(ButtonEvent.Click, () => {
screen.drawText("Right!", 10, 60) screen.print("Right!", 10, 60)
}) })
input.buttonDown.onEvent(ButtonEvent.Click, () => { input.buttonDown.onEvent(ButtonEvent.Click, () => {
screen.drawText("Down! ", 10, 60) screen.print("Down! ", 10, 60)
}) })
input.buttonUp.onEvent(ButtonEvent.Click, () => { input.buttonUp.onEvent(ButtonEvent.Click, () => {
screen.drawText("Up! ", 10, 60) screen.print("Up! ", 10, 60)
}) })
let num = 0 let num = 0
input.touchSensor.onEvent(ButtonEvent.Click, () => { input.touchSensor1.onEvent(TouchSensorEvent.Bumped, () => {
screen.drawText("Click! " + num, 10, 60) screen.print("Click! " + num, 10, 60)
num++ num++
}) })
input.remoteTopLeft.onEvent(ButtonEvent.Click, () => { input.remoteButtonTopLeft.onEvent(ButtonEvent.Click, () => {
screen.drawText("TOPLEFT " + num, 10, 60) screen.print("TOPLEFT " + num, 10, 60)
num++ num++
}) })
input.remoteTopRight.onEvent(ButtonEvent.Down, () => { input.remoteButtonTopRight.onEvent(ButtonEvent.Down, () => {
screen.drawText("TOPRIGH " + num, 10, 60) screen.print("TOPRIGH " + num, 10, 60)
num++ num++
}) })
@ -54,7 +54,7 @@ loops.forever(() => {
/* /*
loops.forever(() => { loops.forever(() => {
let v = input.color.getColor() let v = input.color.getColor()
screen.drawText(10, 60, v + " ") screen.print(10, 60, v + " ")
loops.pause(200) loops.pause(200)
}) })
*/ */

View File

@ -1,10 +1,26 @@
namespace input { // keep TouchSensorEvent in sync with ButtonEvent
export class TouchSensor extends internal.AnalogSensor {
button: Button;
constructor() { /**
super() * Touch sensor interactions
this.button = new Button() */
const enum TouchSensorEvent {
//% block="pressed"
Pressed = 4,
//% block="bumped"
Bumped = 1,
//% block="released"
Released = 3,
}
namespace input {
//% fixedInstances
export class TouchSensor extends internal.AnalogSensor {
private button: Button;
constructor(port: number) {
super(port)
this.button = new Button();
} }
_query() { _query() {
@ -12,17 +28,51 @@ namespace input {
} }
_update(prev: number, curr: number) { _update(prev: number, curr: number) {
this.button.update(curr > 0) this.button._update(curr > 0)
} }
_deviceType() { _deviceType() {
return DAL.DEVICE_TYPE_TOUCH return DAL.DEVICE_TYPE_TOUCH
} }
/**
* Check if touch sensor is touched.
* @param sensor the port to query the request
*/
//% help=input/touch/is-touched
//% block="%sensor|is touched"
//% blockId=touchIsTouched
//% parts="touch"
//% blockNamespace=input
//% weight=81 blockGap=8
//% group="Touch Sensor"
isTouched() {
return this.button.isPressed();
}
/**
* Do something when a touch sensor is touched...
* @param sensor the touch sensor that needs to be clicked or used
* @param event the kind of button gesture that needs to be detected
* @param body code to run when the event is raised
*/
//% help=input/touch/on-event
//% blockId=touchEvent block="on %sensor|%event"
//% parts="touch"
//% blockNamespace=input
//% weight=99 blockGap=8
//% group="Touch Sensor"
onEvent(ev: TouchSensorEvent, body: () => void) {
this.button.onEvent(<ButtonEvent><number>ev, body)
}
} }
//% whenUsed //% whenUsed block="touch sensor 1" weight=95 fixedInstance
export const touchSensorImpl: TouchSensor = new TouchSensor() export const touchSensor1: TouchSensor = new TouchSensor(1)
//% whenUsed block="touch sensor 2" weight=95 fixedInstance
//% whenUsed export const touchSensor2: TouchSensor = new TouchSensor(2)
export const touchSensor: Button = touchSensorImpl.button //% whenUsed block="touch sensor 3" weight=95 fixedInstance
export const touchSensor3: TouchSensor = new TouchSensor(3)
//% whenUsed block="touch sensor 4" weight=95 fixedInstance
export const touchSensor4: TouchSensor = new TouchSensor(4)
} }

View File

@ -1,22 +1,85 @@
const enum PromixityEvent {
//% block="object near"
ObjectNear = 1,
//% block="object detected"
ObjectDetected = 2
}
namespace input { namespace input {
//% fixedInstances
export class UltraSonicSensor extends internal.UartSensor { export class UltraSonicSensor extends internal.UartSensor {
constructor() { private promixityThreshold: number;
super()
constructor(port: number) {
super(port)
this.promixityThreshold = 10;
} }
_deviceType() { _deviceType() {
return DAL.DEVICE_TYPE_ULTRASONIC return DAL.DEVICE_TYPE_ULTRASONIC
} }
/** Get distance in mm */ _query(): number {
getDistance() { const d = this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff;
return d < this.promixityThreshold ? PromixityEvent.ObjectNear
: d > this.promixityThreshold + 5 ? PromixityEvent.ObjectDetected
: 0;
}
_update(prev: number, curr: number) {
if (curr)
control.raiseEvent(this._id, curr);
}
/**
* Registers code to run when the given color is close
* @param handler the code to run when detected
*/
//% help=input/ultrasonic/on-object-near
//% block="on %sensor|object near"
//% blockId=ultrasonicOnObjectClose
//% parts="infraredsensor"
//% blockNamespace=input
//% weight=100 blockGap=8
//% group="Ultrasonic Sensor"
onObjectNear(handler: () => void) {
control.onEvent(this._id, PromixityEvent.ObjectNear, handler);
if (this.distance() == PromixityEvent.ObjectNear)
control.runInBackground(handler);
}
setObjectNearThreshold(distance: number) {
this.promixityThreshold = Math.max(1, Math.min(250, distance));
}
/**
* Gets the distance from the sonar in millimeters
* @param sensor the ultrasonic sensor port
*/
//% help=input/ultrasonic/distance
//% block="%sensor|distance"
//% blockId=sonarGetDistance
//% parts="ultrasonic"
//% blockNamespace=input
//% weight=65 blockGap=8
//% group="Ultrasonic Sensor"
distance() {
// it supposedly also has an inch mode, but we stick to mm // it supposedly also has an inch mode, but we stick to mm
this._setMode(0) this._setMode(0)
return this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff return this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff;
} }
} }
//% whenUsed //% fixedInstance whenUsed block="ultrasonic sensor 4"
export const ultrasonic: UltraSonicSensor = new UltraSonicSensor() export const ultrasonic4: UltraSonicSensor = new UltraSonicSensor(4)
//% fixedInstance whenUsed block="ultrasonic sensor 1"
export const ultrasonic1: UltraSonicSensor = new UltraSonicSensor(1)
//% fixedInstance whenUsed block="ultrasonic sensor 2"
export const ultrasonic2: UltraSonicSensor = new UltraSonicSensor(2)
//% fixedInstance whenUsed block="ultrasonic sensor 3"
export const ultrasonic3: UltraSonicSensor = new UltraSonicSensor(3)
} }

View File

@ -1,11 +1,10 @@
//% color="#D42878" //% color="#D42878"
//% groups='["Brick buttons"]'
namespace input { namespace input {
} }
//% color="#8AC044" weight=90 icon="\uf185" //% color="#8AC044" weight=90 icon="\uf185"
//% groups='["Lights", "Screen", "Motors"]' //% groups='["Motors", "Brick"]'
namespace output { namespace output {
} }

View File

@ -8,15 +8,15 @@
"music.noteFrequency|param|name": "the note name, eg: Note.C", "music.noteFrequency|param|name": "the note name, eg: Note.C",
"music.playSound": "Start playing a sound and don't wait for it to finish.\nNotes are expressed as a string of characters with this format: NOTE[octave][:duration]", "music.playSound": "Start playing a sound and don't wait for it to finish.\nNotes are expressed as a string of characters with this format: NOTE[octave][:duration]",
"music.playSoundUntilDone": "Play a sound and wait until the sound is done.\nNotes are expressed as a string of characters with this format: NOTE[octave][:duration]", "music.playSoundUntilDone": "Play a sound and wait until the sound is done.\nNotes are expressed as a string of characters with this format: NOTE[octave][:duration]",
"music.playSoundUntilDone|param|sound": "the melody to play, eg: 'g5:1'", "music.playSoundUntilDone|param|sound": "the melody to play, eg: music.sounds(Sounds.PowerUp)",
"music.playSound|param|sound": "the melody to play, eg: 'g5:1'", "music.playSound|param|sound": "the melody to play, eg: music.sounds(Sounds.PowerUp)",
"music.playTone": "Play a tone through the speaker for some amount of time.", "music.playTone": "Play a tone through the speaker for some amount of time.",
"music.playTone|param|frequency": "pitch of the tone to play in Hertz (Hz)", "music.playTone|param|frequency": "pitch of the tone to play in Hertz (Hz)",
"music.playTone|param|ms": "tone duration in milliseconds (ms)", "music.playTone|param|ms": "tone duration in milliseconds (ms)",
"music.rest": "Rest, or play silence, for some time (in milleseconds).", "music.rest": "Rest, or play silence, for some time (in milleseconds).",
"music.rest|param|ms": "rest duration in milliseconds (ms)", "music.rest|param|ms": "rest duration in milliseconds (ms), eg: 100",
"music.ringTone": "Play a tone.", "music.ringTone": "Play a tone.",
"music.ringTone|param|frequency": "pitch of the tone to play in Hertz (Hz)", "music.ringTone|param|frequency": "pitch of the tone to play in Hertz (Hz), eg: Note.C",
"music.setTempo": "Set the tempo a number of beats per minute (bpm).", "music.setTempo": "Set the tempo a number of beats per minute (bpm).",
"music.setTempo|param|bpm": "The new tempo in beats per minute, eg: 120", "music.setTempo|param|bpm": "The new tempo in beats per minute, eg: 120",
"music.setVolume": "Set the output volume of the sound synthesizer.", "music.setVolume": "Set the output volume of the sound synthesizer.",

View File

@ -29,14 +29,14 @@
"Sounds.Siren|block": "siren", "Sounds.Siren|block": "siren",
"Sounds.Wawawawaa|block": "wawawawaa", "Sounds.Wawawawaa|block": "wawawawaa",
"music.beat|block": "%fraction|beat", "music.beat|block": "%fraction|beat",
"music.changeTempoBy|block": "change tempo by (bpm)|%value", "music.changeTempoBy|block": "change tempo by %value|(bpm)",
"music.noteFrequency|block": "%note", "music.noteFrequency|block": "%note",
"music.playSoundUntilDone|block": "play sound %sound=music_sounds|until done", "music.playSoundUntilDone|block": "play sound %sound=music_sounds|until done",
"music.playSound|block": "play sound %sound=music_sounds", "music.playSound|block": "play sound %sound=music_sounds",
"music.playTone|block": "play tone|at %note=device_note|for %duration=device_beat", "music.playTone|block": "play tone|at %note=device_note|for %duration=device_beat",
"music.rest|block": "rest|for %duration=device_beat", "music.rest|block": "rest|for %duration=device_beat",
"music.ringTone|block": "ring tone|at %note=device_note", "music.ringTone|block": "ring tone|at %note=device_note",
"music.setTempo|block": "set tempo to (bpm)|%value", "music.setTempo|block": "set tempo to %value|(bpm)",
"music.setVolume|block": "set volume %volume", "music.setVolume|block": "set volume %volume",
"music.sounds|block": "%name", "music.sounds|block": "%name",
"music.stopAllSounds|block": "stop all sounds", "music.stopAllSounds|block": "stop all sounds",

View File

@ -67,10 +67,11 @@ static void _playTone(uint16_t frequency, uint16_t duration, uint8_t volume)
* @param frequency pitch of the tone to play in Hertz (Hz) * @param frequency pitch of the tone to play in Hertz (Hz)
* @param ms tone duration in milliseconds (ms) * @param ms tone duration in milliseconds (ms)
*/ */
//% help=music/play-tone weight=90 //% help=music/play-tone
//% blockId=music_play_note block="play tone|at %note=device_note|for %duration=device_beat" //% blockId=music_play_note block="play tone|at %note=device_note|for %duration=device_beat"
//% parts="headphone" async blockGap=8 //% parts="headphone" async
//% blockNamespace=music //% blockNamespace=music
//% weight=76 blockGap=8
void playTone(int frequency, int ms) { void playTone(int frequency, int ms) {
if (frequency <= 0) { if (frequency <= 0) {
_stopSound(); _stopSound();

View File

@ -18,10 +18,11 @@ declare namespace music {
* @param frequency pitch of the tone to play in Hertz (Hz) * @param frequency pitch of the tone to play in Hertz (Hz)
* @param ms tone duration in milliseconds (ms) * @param ms tone duration in milliseconds (ms)
*/ */
//% help=music/play-tone weight=90 //% help=music/play-tone
//% blockId=music_play_note block="play tone|at %note=device_note|for %duration=device_beat" //% blockId=music_play_note block="play tone|at %note=device_note|for %duration=device_beat"
//% parts="headphone" async blockGap=8 //% parts="headphone" async
//% blockNamespace=music shim=music::playTone //% blockNamespace=music
//% weight=76 blockGap=8 shim=music::playTone
function playTone(frequency: int32, ms: int32): void; function playTone(frequency: int32, ms: int32): void;
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "pxt-ev3", "name": "pxt-ev3",
"version": "0.0.16", "version": "0.0.26",
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode", "description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
"private": true, "private": true,
"keywords": [ "keywords": [
@ -39,8 +39,8 @@
"semantic-ui-less": "^2.2.4" "semantic-ui-less": "^2.2.4"
}, },
"dependencies": { "dependencies": {
"pxt-common-packages": "0.9.2", "pxt-common-packages": "0.11.7",
"pxt-core": "2.0.12" "pxt-core": "2.3.4"
}, },
"scripts": { "scripts": {
"test": "node node_modules/pxt-core/built/pxt.js travis" "test": "node node_modules/pxt-core/built/pxt.js travis"

View File

@ -68,10 +68,10 @@
"appTheme": { "appTheme": {
"accentColor": "#0089BF", "accentColor": "#0089BF",
"logoUrl": "https://lego.makecode.com", "logoUrl": "https://lego.makecode.com",
"logo": "./static/logo.svg", "logo": "./static/lego_education_logo.png",
"docsLogo": "./static/logo.square.svg", "docsLogo": "./static/lego-logo.svg",
"portraitLogo": "./static/logo.square.svg", "portraitLogo": "./static/lego-logo.svg",
"footerLogo": "./static/logo.square.svg", "footerLogo": "./static/lego-logo.svg",
"cardLogo": "./static/icons/android-chrome-192x192.png", "cardLogo": "./static/icons/android-chrome-192x192.png",
"appLogo": "./static/icons/android-chrome-192x192.png", "appLogo": "./static/icons/android-chrome-192x192.png",
"organization": "Microsoft MakeCode", "organization": "Microsoft MakeCode",
@ -89,10 +89,6 @@
"name": "About", "name": "About",
"path": "/about" "path": "/about"
}, },
{
"name": "Examples",
"path": "#projects:Examples"
},
{ {
"name": "Blocks", "name": "Blocks",
"path": "/blocks" "path": "/blocks"
@ -104,22 +100,14 @@
{ {
"name": "Reference", "name": "Reference",
"path": "/reference" "path": "/reference"
},
{
"name": "Buy",
"path": "https://www.lego.com/en-us/mindstorms/products/mindstorms-ev3-31313"
} }
], ],
"galleries": { "showHomeScreen": true,
"Make": "projects", "homeScreenHero": "./static/hero.png",
"Examples": "examples"
},
"sideDoc": "tutorials/getting-started",
"invertedMenu": false, "invertedMenu": false,
"invertedMonaco": false, "invertedMonaco": false,
"monacoToolbox": true, "monacoToolbox": true,
"invertedToolbox": true, "invertedToolbox": true,
"exampleGallery": "examples",
"hasAudio": true, "hasAudio": true,
"usbHelp": [], "usbHelp": [],
"extendEditor": true, "extendEditor": true,

157
scripts/rgf2png.js Executable file
View File

@ -0,0 +1,157 @@
#!/usr/bin/env node
const fs = require("fs")
const zlib = require("zlib")
function compressImg(fn) {
const rgf = fs.readFileSync(fn)
const width = rgf[0]
const height = rgf[1]
const expSz = ((width + 7) >> 3) * height + 2
console.log(`w=${width} h=${height} sz=${rgf.length} exp=${expSz}`)
let crcTable
function crc32(buf) {
if (!crcTable) {
crcTable = []
for (let i = 0; i < 256; i++) {
let curr = i;
for (let j = 0; j < 8; j++) {
if (curr & 1) {
curr = 0xedb88320 ^ (curr >>> 1);
} else {
curr = curr >>> 1;
}
}
crcTable[i] = curr
}
}
let crc = -1;
for (var i = 0; i < buf.length; i++) {
crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
}
return (crc ^ -1) >>> 0;
}
/*
Width 4 bytes
Height 4 bytes
Bit depth 1 byte
Colour type 1 byte
Compression method 1 byte
Filter method 1 byte
Interlace method 1 byte
*/
const chunks = []
function addChunk(mark, addsize) {
const buf = Buffer.alloc(mark.length + addsize)
for (let i = 0; i < mark.length; ++i) {
buf[i] = mark.charCodeAt(i)
}
chunks.push(buf)
return buf
}
const hd = addChunk("IHDR", 4 + 4 + 5)
hd.writeInt32BE(width, 4)
hd.writeInt32BE(height, 8)
hd[12] = 1 // bit depth
hd[13] = 0 // color type - grayscale
hd[14] = 0 // compression - deflate
hd[15] = 0 // filter method
hd[16] = 0 // interlace method - no interlace
const scanlines = []
const scanlen = (width + 7) >> 3
let srcptr = 2
let srcmask = 0x01
for (let y = 0; y < height; ++y) {
const scan = Buffer.alloc(1 + scanlen)
scanlines.push(scan)
let dstptr = 1
let dstmask = 0x80
for (let x = 0; x < width; ++x) {
if (!(rgf[srcptr] & srcmask)) {
scan[dstptr] |= dstmask
}
dstmask >>= 1;
if (dstmask == 0) {
dstmask = 0x80
dstptr++
}
srcmask <<= 1;
if (srcmask > 0x80) {
srcmask = 0x01
srcptr++
}
}
if (srcmask != 0x01) {
srcmask = 0x01
srcptr++
}
if (false) {
// seems to increase file size
scan[0] = 1 // sub
let prev = 0
for (let i = 1; i < scan.length; ++i) {
let p = scan[i]
scan[i] = (p - prev) & 0xff
prev = p
}
}
}
const dat = zlib.deflateSync(Buffer.concat(scanlines), {
level: 9
})
const idat = addChunk("IDAT", dat.length)
dat.copy(idat, 4)
addChunk("IEND", 0)
const output = [new Buffer([137, 80, 78, 71, 13, 10, 26, 10])]
function intBuf(v) {
let b = new Buffer(4)
b.writeUInt32BE(v, 0)
return b
}
for (let ch of chunks) {
output.push(intBuf(ch.length - 4))
output.push(ch)
output.push(intBuf(crc32(ch)))
}
let outp = Buffer.concat(output)
return outp
}
let sz = 0
let bf
let out = {}
for (let i = 2; i < process.argv.length; ++i) {
let fn = process.argv[i]
let m = /([^\/]+\/[^/]+)\.rgf$/.exec(fn)
let bn = m[1]
bf = compressImg(fn)
out[bn] = "data:image/png;base64," + bf.toString("base64")
sz += bf.length
}
console.log("total " + sz)
fs.writeFileSync("out.json", JSON.stringify(out, null, 4))
fs.writeFileSync("out.png", bf)
//if (require("os").platform() == "darwin")
// require('child_process').execSync("afplay out.wav")
// TODO also play on Windows

46
scripts/rsf2wav.js Executable file
View File

@ -0,0 +1,46 @@
#!/usr/bin/env node
const fs = require("fs")
const rsf = fs.readFileSync(process.argv[2])
const fmt = rsf.readInt16BE(0) // 0x0100
if (fmt != 0x0100) {
throw new Error("Invalid input format: " + fmt)
}
const size = rsf.readInt16BE(2)
const samplerate = rsf.readInt16BE(4)
const repeat = rsf.readInt16BE(6)
const datasize = rsf.length - 8
const wavHd = new Buffer(44)
function writeMark(off, mark) {
for (let i = 0; i < mark.length; ++i) {
wavHd[off + i] = mark.charCodeAt(i)
}
}
writeMark(0, 'RIFF')
wavHd.writeInt32LE(datasize + 36, 4)
writeMark(8, 'WAVE')
writeMark(12, 'fmt ')
wavHd.writeInt32LE(16, 16) // fmt size
wavHd.writeInt16LE(1, 20) // PCM
wavHd.writeInt16LE(1, 22) // mono, 1ch
wavHd.writeInt32LE(samplerate, 24)
wavHd.writeInt32LE(samplerate, 28) // byterate
wavHd.writeInt16LE(1, 32) // block align
wavHd.writeInt16LE(8, 34) // bits per sample
writeMark(36, 'data')
wavHd.writeInt32LE(datasize, 40)
const wav = Buffer.concat([wavHd, rsf.slice(8)])
console.log("writing out.wav; " + samplerate + "Hz")
fs.writeFileSync("out.wav", wav)
if (require("os").platform() == "darwin")
require('child_process').execSync("afplay out.wav")
// TODO also play on Windows

View File

@ -25,7 +25,7 @@ namespace pxsim {
export class DalBoard extends CoreBoard implements export class DalBoard extends CoreBoard implements
AccelerometerBoard, AccelerometerBoard,
CommonBoard, CommonBoard,
LightBoard, // LightBoard,
LightSensorBoard, LightSensorBoard,
MicrophoneBoard, MicrophoneBoard,
MusicBoard, MusicBoard,
@ -34,7 +34,7 @@ namespace pxsim {
InfraredBoard, InfraredBoard,
CapTouchBoard { CapTouchBoard {
// state & update logic for component services // state & update logic for component services
neopixelState: CommonNeoPixelState; // neopixelState: CommonNeoPixelState;
buttonState: EV3ButtonState; buttonState: EV3ButtonState;
slideSwitchState: SlideSwitchState; slideSwitchState: SlideSwitchState;
lightSensorState: AnalogSensorState; lightSensorState: AnalogSensorState;
@ -62,11 +62,12 @@ namespace pxsim {
this.builtinParts["buttons"] = this.buttonState = new EV3ButtonState(); this.builtinParts["buttons"] = this.buttonState = new EV3ButtonState();
this.builtinParts["light"] = this.lightState = new EV3LightState(); this.builtinParts["light"] = this.lightState = new EV3LightState();
this.builtinParts["screen"] = this.screenState = new EV3ScreenState(); this.builtinParts["screen"] = this.screenState = new EV3ScreenState();
this.builtinParts["audio"] = this.audioState = new AudioState();
/*this.builtinParts["neopixel"] = this.neopixelState = new CommonNeoPixelState(); /*this.builtinParts["neopixel"] = this.neopixelState = new CommonNeoPixelState();
this.builtinParts["buttonpair"] = this.buttonState = new CommonButtonState(); this.builtinParts["buttonpair"] = this.buttonState = new CommonButtonState();
this.builtinParts["switch"] = this.slideSwitchState = new SlideSwitchState(); this.builtinParts["switch"] = this.slideSwitchState = new SlideSwitchState();
this.builtinParts["audio"] = this.audioState = new AudioState();
this.builtinParts["lightsensor"] = this.lightSensorState = new AnalogSensorState(DAL.DEVICE_ID_LIGHT_SENSOR, 0, 255); this.builtinParts["lightsensor"] = this.lightSensorState = new AnalogSensorState(DAL.DEVICE_ID_LIGHT_SENSOR, 0, 255);
this.builtinParts["thermometer"] = this.thermometerState = new AnalogSensorState(DAL.DEVICE_ID_THERMOMETER, -5, 50); this.builtinParts["thermometer"] = this.thermometerState = new AnalogSensorState(DAL.DEVICE_ID_THERMOMETER, -5, 50);
this.builtinParts["soundsensor"] = this.microphoneState = new AnalogSensorState(DAL.DEVICE_ID_TOUCH_SENSOR + 1, 0, 255); this.builtinParts["soundsensor"] = this.microphoneState = new AnalogSensorState(DAL.DEVICE_ID_TOUCH_SENSOR + 1, 0, 255);
@ -174,9 +175,9 @@ namespace pxsim {
return svg.toDataUri(new XMLSerializer().serializeToString(this.view)); return svg.toDataUri(new XMLSerializer().serializeToString(this.view));
} }
defaultNeopixelPin() { //defaultNeopixelPin() {
return this.edgeConnectorState.getPin(CPlayPinName.D8); // return this.edgeConnectorState.getPin(CPlayPinName.D8);
} //}
getDefaultPitchPin() { getDefaultPitchPin() {
return this.edgeConnectorState.getPin(CPlayPinName.D6); return this.edgeConnectorState.getPin(CPlayPinName.D6);

View File

@ -480,6 +480,7 @@ namespace pxsim.visuals {
this.screenCanvasCtx.putImageData(this.screenCanvasData, 0, 0); this.screenCanvasCtx.putImageData(this.screenCanvasData, 0, 0);
} }
/*
private updateNeoPixels() { private updateNeoPixels() {
let state = this.board; let state = this.board;
if (!state || !state.neopixelState) return; if (!state || !state.neopixelState) return;
@ -509,6 +510,7 @@ namespace pxsim.visuals {
if (p_inner) svg.filter(p_inner, `url(#neopixelglow)`); if (p_inner) svg.filter(p_inner, `url(#neopixelglow)`);
} }
} }
*/
private updateSound() { private updateSound() {
let state = this.board; let state = this.board;

View File

@ -6,5 +6,8 @@
], ],
"approvedRepos": [ "approvedRepos": [
] ]
},
"galleries": {
"Maker Activities": "maker"
} }
} }

View File

@ -34,13 +34,6 @@ span.blocklyTreeLabel {
font-weight: bold; font-weight: bold;
} }
.blocklyFlyoutBackground {
fill: #282828 !important;
}
.monacoFlyout {
background: rgba(40, 40, 40, 0.9);
}
/* Search box */ /* Search box */
#blocklySearchArea { #blocklySearchArea {
margin: 0.5rem; margin: 0.5rem;

View File

@ -22,7 +22,7 @@
/* Lego colors */ /* Lego colors */
@red: @brightRed; @red: @brightRed;
@blue: #008ad2; @blue: #00a5c8; /*#008ad2;*/
@yellow: #fccd00; @yellow: #fccd00;
@orange: #fa7f2a; @orange: #fa7f2a;
@green: @brightYellowishGreen; @green: @brightYellowishGreen;
@ -96,9 +96,11 @@
Menu Menu
--------------------*/ --------------------*/
@mainMenuBackground: #f4f7f9;
@mainMenuInvertedBackground: @yellow; @mainMenuInvertedBackground: @yellow;
@mainMenuTutorialBackground: @orange; @mainMenuTutorialBackground: @orange;
@tutorialSelectedMenuColor: @blue; @tutorialSelectedMenuColor: @blue;
/*------------------- /*-------------------
@ -117,6 +119,8 @@
@editorToolsBackground: #fcfbfa; @editorToolsBackground: #fcfbfa;
@blocklySvgColor: #ecf6ff; @blocklySvgColor: #ecf6ff;
@homeScreenBackground: #EAEEEF;
/*------------------- /*-------------------
Full screen Full screen
--------------------*/ --------------------*/
@ -152,3 +156,13 @@
@blocklyRowHeightComputer: 50px; @blocklyRowHeightComputer: 50px;
@blocklyRowHeightTablet: 50px; @blocklyRowHeightTablet: 50px;
@blocklyRowHeightMobile: 50px; @blocklyRowHeightMobile: 50px;
/*-------------------
Flyout
--------------------*/
@flyoutLabelColor: white;
@blocklyFlyoutColor: #282828;
@blocklyFlyoutColorOpacity: 0.9;
@monacoFlyoutColor: rgba(40, 40, 40,0.9);

View File

@ -44,7 +44,7 @@
/* Menu bar colors */ /* Menu bar colors */
#menubar .ui.item { #menubar .ui.item {
color: @red; color: #373737;
} }
.fullscreensim #menubar .ui.menu { .fullscreensim #menubar .ui.menu {
box-shadow: none !important; box-shadow: none !important;
@ -59,11 +59,17 @@
/* Editor menu toggle */ /* Editor menu toggle */
#menubar .ui.menu.fixed .item.editor-menuitem .ui.grid { #menubar .ui.menu.fixed .item.editor-menuitem .ui.grid {
background: @blue !important; background: @blue !important;
border-radius: 0px !important;
} }
#menubar .ui.menu.fixed .ui.item.editor-menuitem .item:not(.active) { #menubar .ui.menu.fixed .ui.item.editor-menuitem .item:not(.active) {
color: white; color: white;
} }
#menubar .ui.menu.fixed .ui.item.editor-menuitem .item {
border-radius: 0px !important;
}
#menubar .ui.menu.fixed .ui.item.editor-menuitem .item.active {
color: @blue;
}
.sandboxfooter a:not(.thin) { .sandboxfooter a:not(.thin) {
color:white !important; color:white !important;

View File

@ -49,10 +49,10 @@
/* Modules */ /* Modules */
@accordion : 'default'; @accordion : 'default';
@checkbox : 'default'; @checkbox : 'default';
@dimmer : 'default'; @dimmer : 'pxt';
@dropdown : 'default'; @dropdown : 'default';
@embed : 'default'; @embed : 'default';
@modal : 'default'; @modal : 'pxt';
@nag : 'default'; @nag : 'default';
@popup : 'default'; @popup : 'default';
@progress : 'default'; @progress : 'default';
@ -66,7 +66,7 @@
/* Views */ /* Views */
@ad : 'default'; @ad : 'default';
@card : 'default'; @card : 'pxt';
@comment : 'default'; @comment : 'default';
@feed : 'default'; @feed : 'default';
@item : 'default'; @item : 'default';