Compare commits

...

33 Commits

Author SHA1 Message Date
ba1b9a54b4 0.0.79 2018-01-30 22:41:37 -08:00
59e39fa76d fixing field width 2018-01-30 22:41:18 -08:00
9187c47e09 0.0.78 2018-01-30 22:22:44 -08:00
fcf91caeb4 Zoom screen (#285)
* always start with full brick layout

* adding 'on start' to template

* render entire board when selected

* zoom brick when clicking on screen

* resize when zooming

* toggle zooming of the brick

* inject close icon when selected

* fix toggling
2018-01-30 22:22:21 -08:00
822227eb48 Brick ref topics 02 (#283)
* Add brick button topics

* Add the rest of the brick api
2018-01-30 20:58:18 -08:00
8a331648d6 Field editor fixes in Firefox (#284)
* fixing speed field picker

* switching to open sans

* alignment-baseline not support in FF
2018-01-30 20:40:41 -08:00
4f70d341e4 Start on the 'brick' api topics (#280)
* Start on the 'brick' api topics

* Add the delay to clear screen example

* Better output for clearsceen example
2018-01-30 17:02:22 -08:00
e06659ab4c removing group icons (#282) 2018-01-30 16:40:08 -08:00
437c36b983 0.0.77 2018-01-30 16:16:07 -08:00
3d73f193a8 fix for #260 (#279) 2018-01-30 16:14:54 -08:00
a71dee2923 rebuild for sampling (#261)
* rebuild for sampling

* bump pxt
2018-01-30 16:01:12 -08:00
9ef5b8d4ad 0.0.76 2018-01-30 11:05:29 -08:00
8aa47f3d1e updated chassis (#250) 2018-01-30 08:49:10 -08:00
02b0716043 0.0.75 2018-01-30 08:28:12 -08:00
188d5b3aa7 threshold query api 2018-01-30 08:27:23 -08:00
16c67f0e30 Refactoring datalog in common packages (#249)
* using datalog from common packages

* upgrading common package link

* updated block signatures

* more docs
2018-01-29 19:46:54 -08:00
104185a41e 0.0.74 2018-01-29 15:21:37 -08:00
73363d11b2 Download dialog (#248)
* download dialog

* updated pxt reference

* typo
2018-01-29 15:21:15 -08:00
61996acdd9 0.0.73 2018-01-29 13:26:46 -08:00
21deb45728 fixing release fiber 2018-01-29 13:26:31 -08:00
34578d2370 0.0.72 2018-01-29 11:20:46 -08:00
3f50b5c39a updated pxt references + hero banner 2018-01-29 11:20:34 -08:00
d371225066 0.0.71 2018-01-23 14:53:09 -08:00
387effbdd0 upgraded to run in parallel 2018-01-23 14:52:41 -08:00
18480080e7 updated tutorial format 2018-01-19 15:42:23 -08:00
bf6a932e5f Color calibration (#245)
* better handling of thresholds, color calibration strategy

* updating calibration parameters
2018-01-19 13:11:11 -08:00
23bb316403 settle robot once brake is applied 2018-01-18 21:28:00 -08:00
138de504e5 minor high contrast fixes 2018-01-18 21:03:57 -08:00
df13e40a45 fixing make it move 2018-01-18 16:47:00 -08:00
511ea2374b fixing summary 2018-01-18 16:44:57 -08:00
db4ed6daf3 fixing a bunch of snippets 2018-01-18 16:43:16 -08:00
a60427e2cf using audio context manager function (#243)
* using audio context manager function

* updated pxt reference

* trigger build
2018-01-18 13:53:33 -08:00
ef5b4172e8 missing file logo 2018-01-18 12:42:11 -08:00
96 changed files with 2103 additions and 454 deletions

View File

@ -1,6 +1,38 @@
# @extends # @extends
## Lessons #Lessons ## Projects #projects
* [Maker](/maker)
* [Sound Machine](/maker/sound-machine)
* [Sound of Color](/maker/sound-of-color)
* [Security Gadget](/maker/security-gadget)
* [Intruder detector](/maker/intruder-detector)
* [Puppet](/maker/puppet)
* [Coding](/coding)
* [Three Point Turn 1](/coding/three-point-turn-1)
* [Three Point Turn 2](/coding/three-point-turn-2)
* [Three Point Turn 3](/coding/three-point-turn-3)
* [Reversing the robot 1](/coding/reversing-the-robot-1)
* [Reversing the robot 2](/coding/reversing-the-robot-2)
* [Reversing the robot 3](/coding/reversing-the-robot-3)
* [Light the way 1](/coding/light-the-way-1)
* [Light the way 2](/coding/light-the-way-2)
* [Light the way 3](/coding/light-the-way-3)
* [Traffic Lights 1](/coding/traffic-lights-1)
* [Traffic Lights 2](/coding/traffic-lights-2)
* [Traffic Lights 3](/coding/traffic-lights-3)
* [Reverse Beeper 1](/coding/reverse-beeper-1)
* [Reverse Beeper 2](/coding/reverse-beeper-2)
* [Reverse Beeper 3](/coding/reverse-beeper-3)
* [Ignition 1](/coding/ignition-1)
* [Ignition 2](/coding/ignition-2)
* [Ignition 3](/coding/ignition-3)
* [Cruise Control 1](/coding/cruise-control-1)
* [Cruise Control 2](/coding/cruise-control-2)
* [Cruise Control 3](/coding/cruise-control-3)
* [Roaming 1](/coding/roaming-1)
* [Roaming 2](/coding/roaming-2)
* [Lessons](/lessons) * [Lessons](/lessons)
* [Make it move](/lessons/make-it-move) * [Make it move](/lessons/make-it-move)
@ -9,3 +41,17 @@
## Reference #reference ## Reference #reference
* [Reference](/reference) * [Reference](/reference)
* [Brick](/reference/brick)
* [show string](/reference/brick/show-string)
* [show number](/reference/brick/show-number)
* [show value](/reference/brick/show-value)
* [show mood](/reference/brick/show-mood)
* [show image](/reference/brick/show-image)
* [clear screen](/reference/brick/clear-screen)
* [print ports](/reference/brick/print-ports)
* [on event](/reference/brick/button/on-event)
* [is pressed](/reference/brick/button/is-pressed)
* [was pressed](/reference/brick/button/was-pressed)
* [pause until](/reference/brick/button/pause-until)
* [set light](/reference/brick/set-light)
* [battery level](/reference/brick/battery-level)

View File

@ -6,14 +6,14 @@ Welcome to the **Microsoft MakeCode** editor for the **@boardname@**!
You can program the @boardname@ using [Blocks](/blocks) or [JavaScript](/javascript) in your web browser: You can program the @boardname@ using [Blocks](/blocks) or [JavaScript](/javascript) in your web browser:
```block ```blocks
input.buttonA.onEvent(ButtonEvent.Click, () => { brick.buttonEnter.onEvent(ButtonEvent.Click, () => {
light.showRing(`blue blue blue blue blue blue blue blue blue blue`) motors.largeA.setSpeed(50)
}) })
``` ```
```typescript ```typescript
input.buttonA.onEvent(ButtonEvent.Click, () => { brick.buttonEnter.onEvent(ButtonEvent.Click, () => {
light.showRing(`blue blue blue blue blue blue blue blue blue blue`) motors.largeA.setSpeed(50)
}) })
``` ```
@ -22,10 +22,10 @@ The editor work in [most modern browsers](/browsers), work [offline](/offline) o
## [Compile and Flash: Your Program!](/device/usb) ## [Compile and Flash: Your Program!](/device/usb)
When you have your code ready, you connect your @boardname@ to a computer via a USB cable When you have your code ready, you connect your @boardname@ to a computer via a USB cable
**then press the reset button** so it appears as a mounted drive (named **CPLAYBOOT**). so it appears as a mounted drive (named **EV3**).
Compilation to machine code from [Blocks](/blocks) or [JavaScript](/javascript) happens in the browser. You save the binary Compilation to machine code from [Blocks](/blocks) or [JavaScript](/javascript) happens in the browser. You save the binary
program to a **.uf2** file, which you then copy to the **CPLAYBOOT** drive, which flashes the device with the new program. program to a **.uf2** file, which you then copy to the **EV3** drive, which flashes the device with the new program.
## Simulator: Test Your Code ## Simulator: Test Your Code
@ -33,11 +33,7 @@ You can run your code using the micro:bit simulator, all within the confines of
The simulator has support for the LED screen, buttons, as well as compass, accelerometer, and digital I/O pins. The simulator has support for the LED screen, buttons, as well as compass, accelerometer, and digital I/O pins.
```sim ```sim
loops.forever(() => { brick.buttonEnter.onEvent(ButtonEvent.Click, () => {
light.pixels.showAnimation(light.animation(LightAnimation.Rainbow), 1000) motors.largeA.setSpeed(50)
}) })
``` ```
```package
light
```

View File

@ -3,13 +3,13 @@
```blocks ```blocks
let beep = false let beep = false
beep = true beep = true
control.runInBackground(function () { control.runInParallel(function () {
motors.largeBC.setSpeed(-20) motors.largeBC.setSpeed(-20)
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear) sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear)
motors.largeBC.stop() motors.largeBC.stop()
beep = false beep = false
}) })
control.runInBackground(function () { control.runInParallel(function () {
while (beep) { while (beep) {
if (sensors.ultrasonic4.distance() < 20) { if (sensors.ultrasonic4.distance() < 20) {
music.playTone(440, sensors.ultrasonic4.distance()) music.playTone(440, sensors.ultrasonic4.distance())

View File

@ -3,10 +3,10 @@
```blocks ```blocks
brick.buttonEnter.onEvent(ButtonEvent.Click, function () { brick.buttonEnter.onEvent(ButtonEvent.Click, function () {
motors.largeBC.setSpeed(50) motors.largeBC.setSpeed(50)
sensors.touchSensor1.pauseUntil(TouchSensorEvent.Pressed) sensors.touch1.pauseUntil(TouchSensorEvent.Pressed)
motors.largeBC.setSpeed(0) motors.largeBC.setSpeed(0)
loops.pause(1000) loops.pause(1000)
brick.setLight(LightsPattern.OrangeFlash) brick.setLight(BrickLight.OrangeFlash)
motors.largeBC.setSpeed(-50) motors.largeBC.setSpeed(-50)
loops.pause(2000) loops.pause(2000)
motors.largeBC.setSpeed(0) motors.largeBC.setSpeed(0)

View File

@ -2,12 +2,12 @@
```blocks ```blocks
brick.buttonEnter.onEvent(ButtonEvent.Click, function () { brick.buttonEnter.onEvent(ButtonEvent.Click, function () {
sensors.touchSensor1.pauseUntil(TouchSensorEvent.Pressed) sensors.touch1.pauseUntil(TouchSensorEvent.Pressed)
motors.largeBC.setSpeed(50) motors.largeBC.setSpeed(50)
sensors.touchSensor2.pauseUntil(TouchSensorEvent.Pressed) sensors.touch2.pauseUntil(TouchSensorEvent.Pressed)
motors.largeBC.setSpeed(0) motors.largeBC.setSpeed(0)
loops.pause(1000) loops.pause(1000)
brick.setLight(LightsPattern.OrangeFlash) brick.setLight(BrickLight.OrangeFlash)
motors.largeBC.setSpeed(-50) motors.largeBC.setSpeed(-50)
loops.pause(2000) loops.pause(2000)
motors.largeBC.setSpeed(0) motors.largeBC.setSpeed(0)

View File

@ -3,14 +3,14 @@
```blocks ```blocks
brick.buttonEnter.onEvent(ButtonEvent.Click, function () { brick.buttonEnter.onEvent(ButtonEvent.Click, function () {
brick.showImage(images.eyesSleeping) brick.showImage(images.eyesSleeping)
sensors.touchSensor1.pauseUntil(TouchSensorEvent.Pressed) sensors.touch1.pauseUntil(TouchSensorEvent.Pressed)
brick.showImage(images.eyesNeutral) brick.showImage(images.eyesNeutral)
motors.largeBC.setSpeed(50) motors.largeBC.setSpeed(50)
sensors.touchSensor2.pauseUntil(TouchSensorEvent.Pressed) sensors.touch2.pauseUntil(TouchSensorEvent.Pressed)
brick.showImage(images.eyesTiredMiddle) brick.showImage(images.eyesTiredMiddle)
motors.largeBC.setSpeed(0) motors.largeBC.setSpeed(0)
loops.pause(1000) loops.pause(1000)
brick.setLight(LightsPattern.OrangeFlash) brick.setLight(BrickLight.OrangeFlash)
brick.showImage(images.eyesDizzy) brick.showImage(images.eyesDizzy)
motors.largeBC.setSpeed(-50) motors.largeBC.setSpeed(-50)
loops.pause(2000) loops.pause(2000)

View File

@ -19,17 +19,13 @@ loops.pause(1000)
music.playSoundEffectUntilDone(sounds.communicationGo) music.playSoundEffectUntilDone(sounds.communicationGo)
for (let d of drive) { for (let d of drive) {
if (d == 1) { if (d == 1) {
motors.largeC.setSpeedFor(50, 360, MoveUnit.Degrees) motors.largeC.setSpeed(50, 360, MoveUnit.Degrees)
motors.largeC.pauseUntilReady()
} else if (d == 3) { } else if (d == 3) {
motors.largeB.setSpeedFor(50, 360, MoveUnit.Degrees) motors.largeB.setSpeed(50, 360, MoveUnit.Degrees)
motors.largeB.pauseUntilReady()
} else if (d == 4) { } else if (d == 4) {
motors.largeBC.setSpeedFor(50, 360, MoveUnit.Degrees) motors.largeBC.setSpeed(50, 360, MoveUnit.Degrees)
motors.largeBC.pauseUntilReady()
} else { } else {
motors.largeBC.setSpeedFor(-50, 360, MoveUnit.Degrees) motors.largeBC.setSpeed(-50, 360, MoveUnit.Degrees)
motors.largeBC.pauseUntilReady()
} }
} }
music.playSoundEffectUntilDone(sounds.communicationGameOver) music.playSoundEffectUntilDone(sounds.communicationGameOver)

View File

@ -23,17 +23,13 @@ loops.pause(1000)
music.playSoundEffectUntilDone(sounds.communicationGo) music.playSoundEffectUntilDone(sounds.communicationGo)
for (let d of drive) { for (let d of drive) {
if (d == 1) { if (d == 1) {
motors.largeC.setSpeedFor(50, 360, MoveUnit.Degrees) motors.largeC.setSpeed(50, 360, MoveUnit.Degrees)
motors.largeC.pauseUntilReady()
} else if (d == 3) { } else if (d == 3) {
motors.largeB.setSpeedFor(50, 360, MoveUnit.Degrees) motors.largeB.setSpeed(50, 360, MoveUnit.Degrees)
motors.largeB.pauseUntilReady()
} else if (d == 4) { } else if (d == 4) {
motors.largeBC.setSpeedFor(50, 360, MoveUnit.Degrees) motors.largeBC.setSpeed(50, 360, MoveUnit.Degrees)
motors.largeBC.pauseUntilReady()
} else { } else {
motors.largeBC.setSpeedFor(-50, 360, MoveUnit.Degrees) motors.largeBC.setSpeed(-50, 360, MoveUnit.Degrees)
motors.largeBC.pauseUntilReady()
} }
} }
music.playSoundEffectUntilDone(sounds.communicationGameOver) music.playSoundEffectUntilDone(sounds.communicationGameOver)

View File

@ -81,7 +81,7 @@ function IS(t: number) {
function UP() { function UP() {
if (motors.largeA.angle() > -50) { if (motors.largeA.angle() > -50) {
control.runInBackground(function () { control.runInParallel(function () {
motors.largeD.clearCounts() motors.largeD.clearCounts()
motors.largeD.setSpeed(-35); motors.largeD.setSpeed(-35);
pauseUntil(() => motors.largeD.angle() < -25); pauseUntil(() => motors.largeD.angle() < -25);

View File

@ -3,10 +3,10 @@
Use a touch sensor to make the brick happy. Use a touch sensor to make the brick happy.
```blocks ```blocks
sensors.touchSensor1.onEvent(TouchSensorEvent.Pressed, function () { sensors.touch1.onEvent(TouchSensorEvent.Pressed, function () {
brick.showImage(images.expressionsBigSmile) brick.showImage(images.expressionsBigSmile)
}) })
sensors.touchSensor1.onEvent(TouchSensorEvent.Released, function () { sensors.touch1.onEvent(TouchSensorEvent.Released, function () {
brick.showImage(images.expressionsSick) brick.showImage(images.expressionsSick)
}) })
``` ```

View File

@ -1,6 +1,6 @@
# Make It Move Without Wheels # Make It Move Without Wheels
## Objective @fullscreen ## Objective @unplugged
Design, build and program a robot that can move itself: Design, build and program a robot that can move itself:
@ -13,7 +13,7 @@ Your robot will:
![LECG Mindstorms brick with parts](/static/lessons/make-it-move/locomotion-no-wheels.jpg) ![LECG Mindstorms brick with parts](/static/lessons/make-it-move/locomotion-no-wheels.jpg)
## Construct @fullscreen ## Construct @unplugged
Build a Walker Bot! Build a Walker Bot!
@ -67,6 +67,6 @@ motors.stopAllMotors()
brick.showString("30 cm", 1) brick.showString("30 cm", 1)
``` ```
## Program 4 @fullscreen ## Download @fullscreen
Click `|Download|` and follow the instructions to get your code onto your EV3 Brick. Press the **center** button on the EV3 Brick to run the program. Click `|Download|` and follow the instructions to get your code onto your EV3 Brick. Press the **center** button on the EV3 Brick to run the program.

View File

@ -40,8 +40,8 @@ Change the rotations to `9`.
The ``||motors:tank large B+C||`` block will run for `9` rotations when the **center** button is pressed on the EV3 brick. The motors are set for the reverse direction because they are mounted upside down in this model. The ``||motors:tank large B+C||`` block will run for `9` rotations when the **center** button is pressed on the EV3 brick. The motors are set for the reverse direction because they are mounted upside down in this model.
```typescript-ignore ```blocks
motors.largeBC.tankFor(-60, 60, 9, MoveUnit.Rotations) motors.largeBC.tank(-60, 60, 9, MoveUnit.Rotations)
``` ```
### Step 2 ### Step 2
@ -50,9 +50,9 @@ Place a ``||motors:stop all motors||`` block under ``||motors:tank large B+C||``
The ``||motors:tank large B+C||`` block will run for `9` rotations when the **center** button is pressed on the EV3 brick then stop. The ``||motors:tank large B+C||`` block will run for `9` rotations when the **center** button is pressed on the EV3 brick then stop.
```typescript-ignore ```blocks
motors.largeBC.tankFor(-60, 60, 9, MoveUnit.Rotations) motors.largeBC.tank(-60, 60, 9, MoveUnit.Rotations)
motors.stopAllMotors() motors.largeBC.stop()
``` ```
### Step 3 ### Step 3
@ -62,9 +62,9 @@ Change the `"Hello World"` text to `"30 cm"`.
The ``||motors:tank large B+C||`` will run for `9` rotations when the **center** button is pressed on the EV3 brick then stop and display "30 cm" on the EV3 Bricks screen. The ``||motors:tank large B+C||`` will run for `9` rotations when the **center** button is pressed on the EV3 brick then stop and display "30 cm" on the EV3 Bricks screen.
```typescript-ignore ```blocks
motors.largeBC.tankFor(-60, 60, 9, MoveUnit.Rotations) motors.largeBC.tank(-60, 60, 9, MoveUnit.Rotations)
motors.stopAllMotors() motors.largeBC.stop()
brick.showString("30 cm", 1) brick.showString("30 cm", 1)
``` ```

View File

@ -2,10 +2,8 @@
This program will activate an alarm when an object moves in front of the Ultrasonic Sensor. This program will activate an alarm when an object moves in front of the Ultrasonic Sensor.
TODO support for event when value changes
```blocks ```blocks
input.ultrasonic4.onObjectNear(function () { sensors.ultrasonic4.onEvent(UltrasonicSensorEvent.ObjectNear, function () {
music.playSoundUntilDone(music.sounds(Sounds.PowerUp)) music.playSoundEffectUntilDone(sounds.informationActivate)
}) })
``` ```

View File

@ -4,14 +4,12 @@ Use this program with the Programmable Brick and Large Motor.
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
output.largeMotorA.setPower(30) motors.largeA.setSpeed(30)
output.largeMotorA.on(true)
loops.pause(100) loops.pause(100)
output.largeMotorA.on(false) motors.largeA.stop()
music.playSoundUntilDone(music.sounds(Sounds.PowerUp)) music.playSoundEffectUntilDone(sounds.animalsCatPurr)
output.largeMotorA.setPower(-30) motors.largeA.setSpeed(-30)
output.largeMotorA.on(true)
loops.pause(100) loops.pause(100)
output.largeMotorA.on(false) motors.largeA.stop()
}) })
``` ```

View File

@ -3,7 +3,7 @@
This program will activate an alarm when an object is lifted from the Touch Sensor. This program will activate an alarm when an object is lifted from the Touch Sensor.
```blocks ```blocks
input.touchSensor1.onEvent(TouchSensorEvent.Released, function () { sensors.touch1.onEvent(TouchSensorEvent.Released, function () {
music.playSoundUntilDone(music.sounds(Sounds.PowerUp)) music.playSoundEffectUntilDone(sounds.informationActivate);
}) })
``` ```

View File

@ -4,9 +4,9 @@ This example program combined with the small model will make a beat and rhythm o
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
output.motorA.on(50) motors.largeA.setSpeed(50)
loops.pause(200) loops.pause(200)
output.motorA.on(100) motors.largeA.setSpeed(100)
loops.pause(200) loops.pause(200)
}) })
``` ```

View File

@ -3,13 +3,13 @@
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. 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 ```blocks
input.color3.onColorDetected(ColorSensorColor.Blue, function () { sensors.color3.onColorDetected(ColorSensorColor.Blue, function () {
music.playTone(Note.G4, music.beat(BeatFraction.Half)) music.playTone(Note.G4, music.beat(BeatFraction.Half))
}) })
input.color3.onColorDetected(ColorSensorColor.Red, function () { sensors.color3.onColorDetected(ColorSensorColor.Red, function () {
music.playTone(Note.C5, music.beat(BeatFraction.Half)) music.playTone(Note.C5, music.beat(BeatFraction.Half))
}) })
input.color3.onColorDetected(ColorSensorColor.Green, function () { sensors.color3.onColorDetected(ColorSensorColor.Green, function () {
music.playTone(Note.D5, music.beat(BeatFraction.Half)) music.playTone(Note.D5, music.beat(BeatFraction.Half))
}) })
``` ```

View File

@ -1,8 +1,11 @@
# Reference # Reference
```namespaces
brick.showMood(moods.sleeping);
```
## See Also ## See Also
[brick](/reference/brick),
[touch sensor](/reference/sensors/touch-sensor), [touch sensor](/reference/sensors/touch-sensor),
[color sensor](/reference/sensors/color-sensor) [color sensor](/reference/sensors/color-sensor)

31
docs/reference/brick.md Normal file
View File

@ -0,0 +1,31 @@
# Brick
## Screen
```cards
brick.showMood(moods.sleeping);
brick.showImage(images.expressionsBigSmile);
brick.showString("Hello world!", 1);
brick.showNumber(0, 1);
brick.showValue("item", 0, 1);
brick.clearScreen();
brick.printPorts();
```
## Buttons
```cards
brick.buttonEnter.onEvent(ButtonEvent.Click, function () {
});
brick.buttonEnter.pauseUntil(ButtonEvent.Click);
brick.buttonEnter.isPressed()
brick.buttonEnter.wasPressed()
brick.setLight(BrickLight.Red);
```
## Other
```cards
brick.batteryLevel()
```

View File

@ -0,0 +1,33 @@
# battery Level
Return the current battery level.
```sig
brick.batteryLevel();
```
## Returns
* a [number](/types/number) which is the current charge level of the brick's battery. This is a percentage of total charge left in the battery.
## Example
Show the battery level percentage on the screen. Also, show a green light if the battery level is above 15%. If the battery level is below 15% but above 5%, show a orange light. But, if the battery level is below 5%, show a pulsing red light.
```blocks
let battery = 0;
loops.forever(function() {
brick.showString("Battery level:", 1)
brick.showNumber(battery, 2)
battery = brick.batteryLevel();
if (battery > 15)
{
brick.setLight(BrickLight.Green);
} else if (battery > 5) {
brick.setLight(BrickLight.Orange);
} else {
brick.setLight(BrickLight.RedPulse)
}
loops.pause(30000)
})
```

View File

@ -0,0 +1,53 @@
# is Pressed
Check if a button is being pressed or not.
```sig
brick.buttonEnter.isPressed()
```
## ~hint
**Touch sensors**
Your @boardname@ has touch sensors that work like buttons. Instead of saying `enter` or `left` as the source button, use a touch sensor block with a sensor name like `touch 1`.
```block
if (sensors.touch1.isPressed()) {
console.log("Hey, I feel pressed.");
}
```
Read about [touch sensors](/reference/sensors/touch-sensor) and using them as touch buttons.
## ~
## Returns
* a [boolean](types/boolean): `true` if the button is pressed, `false` if the button is not pressed
## Example
Set the brick light to green when the `down` is pressed. When the button is not pressed, the brick light is red.
```blocks
let isRed = false;
loops.forever(function() {
if (brick.buttonLeft.isPressed()) {
brick.setLight(BrickLight.Green);
isRed = false;
} else {
if (!isRed) {
brick.setLight(BrickLight.Red);
isRed = true;
}
}
})
```
## See also
[was pressed](/reference/brick/button/was-pressed),
[on event](/reference/brick/button/on-event)
[Touch sensors](/reference/sensors/touch-sensor)

View File

@ -0,0 +1,57 @@
# on Event
Run some code when a button is clicked, pressed down, or released.
```sig
brick.buttonEnter.onEvent(ButtonEvent.Click, function () {
});
```
## ~hint
**Touch sensors**
Your @boardname@ has touch sensors that work like buttons. Instead of saying `enter` or `left` as the source button, use a touch sensor block with a sensor name like `touch 1`.
```block
sensors.touch1.onEvent(TouchSensorEvent.Pressed, function () {
brick.setLight(BrickLight.Orange);
});
```
Read about [touch sensors](/reference/sensors/touch-sensor) and using them as touch buttons.
## ~
## Parameters
* **ev**: the button action to run some code for. The button actions (events) are:
> * ``click``: button was clicked (pressed and released)
> * ``up``: button is released from just being pressed
> * ``down``: button is just pressed down
* **body**: the code you want to run when something happens with a button
## Example
Check for event on the ENTER button. Put a message on the screen when the button is pressed, clicked, or released.
```blocks
brick.showString("ENTER is: UP", 1);
brick.buttonEnter.onEvent(ButtonEvent.Up, function () {
brick.showString("ENTER is: UP ", 1);
});
brick.buttonEnter.onEvent(ButtonEvent.Down, function () {
brick.showString("ENTER is: DOWN ", 1);
});
brick.buttonEnter.onEvent(ButtonEvent.Click, function () {
brick.showString("ENTER was: CLICKED", 1);
});
```
### See also
[is pressed](/reference/brick/button/is-pressed),
[was pressed](/reference/brick/button/was-pressed),
[Touch sensor](/reference/sensors/touch-sensor)

View File

@ -0,0 +1,37 @@
# pause Until
Causes your program to wait until an event at a button happens.
```sig
brick.buttonEnter.pauseUntil(ButtonEvent.Click);
```
## Parameters
* **ev**: the button action to wait for. The button actions (events) are:
> * ``click``: button was clicked (pressed and released)
> * ``up``: button is released from just being pressed
> * ``down``: button is just pressed down
## Example
Wait for the `up` button to go up before continuing with displaying a message on the screen.
```blocks
let waitTime = 0;
brick.showString("We're going to wait", 1);
brick.showString("for you to press and", 2);
brick.showString("release the UP button", 3);
waitTime = control.millis();
brick.buttonUp.pauseUntil(ButtonEvent.Click);
brick.clearScreen();
if (control.millis() - waitTime > 5000) {
brick.showString("Ok, that took awhile!", 1)
} else {
brick.showString("Ah, you let go!", 1)
}
```
## See also
[on event](/reference/brick/button/on-event)

View File

@ -0,0 +1,50 @@
# was Pressed
Check if a button was pressed earlier.
```sig
brick.buttonEnter.wasPressed()
```
The fact that a button was pressed earlier is remembered. Once **was pressed** is used, this fact is forgotten and the result is `false` the next time you check with **was pressed** button _state_ is reset). But, if you press the button again before you check with **was pressed**, it will tell you `true`.
## ~hint
**Touch sensors**
Your @boardname@ has touch sensors that work like buttons. Instead of saying `enter` or `left` as the source button, use a touch sensor block with a sensor name like `touch 1`.
```block
if (sensors.touch1.wasPressed()) {
console.log("Hey, I was pressed.");
}
```
Read about [touch sensors](/reference/sensors/touch-sensor) and using them as touch buttons.
## ~
## Returns
* a [boolean](types/boolean): `true` if the button was pressed before, `false` if the button was not pressed before
## Example
Set the brick light to green if the `right` button was pressed before the `left` button. If not, the brick light is turned off when the `left` button is pressed.
```blocks
brick.buttonLeft.onEvent(ButtonEvent.Click, function() {
if (brick.buttonRight.wasPressed()) {
brick.setLight(BrickLight.Green)
} else {
brick.setLight(BrickLight.Off)
}
})
```
## See also
[is pressed](/reference/brick/button/is-pressed),
[on event](/reference/brick/button/on-event)
[Touch sensors](/reference/sensors/touch-sensor)

View File

@ -0,0 +1,22 @@
# clear Screen
Clear any text or numbers displayed on the screen. The screen will be blank.
```sig
brick.clearScreen();
```
## Example
Clear the screen after displaying the message.
```blocks
brick.showString("This message will", 1);
brick.showString("self-destruct in:", 2);
brick.showString("seconds", 5);
for (let i = 0; i < 10; i++) {
brick.showNumber(10 - i, 4);
loops.pause(1000);
}
brick.clearScreen();
```

View File

@ -0,0 +1,19 @@
# print Ports
Print the status of the ports on the screen.
```sig
brick.printPorts();
```
## Example
Show the port status.
```blocks
brick.printPorts();
```
## See also
[show string](/reference/brick/show-string), [show value](/reference/brick/show-value)

View File

@ -0,0 +1,37 @@
# set Light
Set the light on the brick to a solid or flashing color.
```sig
brick.setLight(BrickLight.Red);
```
## Parameters
* **pattern**: the color or color pattern for the brick light to show. The brick light can have these color patterns:
>* `off`: brick light is off
>* `green`: solid green
>* `red`: solid red
>* `orange`: solid orange
>* `green flash`: flashing green
>* `red flash`: flashing red
>* `orange flash`: flashing orange
>* `green pulse`: pulsing green
>* `red pulse`: pulsing red
>* `orange pulse`: pulsing orange
## Example
Repeatedly show a different color pattern for the brick light.
```blocks
loops.forever(function () {
brick.setLight(BrickLight.Orange)
loops.pause(1000)
brick.setLight(BrickLight.GreenFlash)
loops.pause(2000)
brick.setLight(BrickLight.RedPulse)
loops.pause(2000)
brick.setLight(BrickLight.Off)
loops.pause(500)
})
```

View File

@ -0,0 +1,24 @@
# show Image
Show an image on the brick's display.
```sig
brick.showImage(images.expressionsBigSmile);
```
You can choose one of several images to show on the display.
## Parameters
**image**: A image to show on the brick's display. Use the image picker to choose the image you want to show.
## Example
Show a sleeping image on the brick's display.
```blocks
brick.showImage(images.expressionsZzz)
```
## See also
[show image](/reference/brick/show-mood)

View File

@ -0,0 +1,24 @@
# show Number
Show a number on the screen at the line you select.
```sig
brick.showNumber(0, 1);
```
## Parameters
* **value**: a [number](/types/number) to show on the brick's screen.
* **line**: The line number on the screen where the value is displayed. The line numbers for the screen start with line `1`.
## Example
Show the number `1000` on the screen.
```blocks
brick.showNumber(1000, 1);
```
## See also
[show string](/reference/brick/show-string), [show value](/reference/brick/show-value)

View File

@ -0,0 +1,29 @@
# show String
Show some text on a the screen at the line you select.
```sig
brick.showString("Hello world", 1)
```
## Parameters
* **text**: a [string](/types/string) to show on the brick's screen.
* **line**: the line [number](/types/number) on the screen where the text is displayed. The line numbers for the screen start with line `1`.
## Example
Show a greeting on the screen. Then, respond with another message when ENTER is pressed.
```blocks
brick.showString("Hello, I dare you to", 1);
brick.showString("press ENTER...", 2);
brick.buttonEnter.onEvent(ButtonEvent.Click, function () {
brick.showString("Hey! Don't push my", 4);
brick.showString("buttons.", 5);
});
```
## See also
[show number](/reference/brick/show-number)

View File

@ -0,0 +1,29 @@
# show Value
Show a name-value-pair on the screen at the line you select.
```sig
brick.showNumber("item", 0, 1);
```
Name-value-pairs are used to report data values to the screen. If you want to show the current temperature on the screen, you might use `"temp"` as the data name for the the value.
## Parameters
* **name**: a [string](/types/string) which is the name of the data value.
* **value**: a [number](/types/number) to show on the brick's screen.
* **line**: The line number on the screen where the value is displayed. The line numbers for the screen start with line `1`.
## Example
Show the current amount of ambient light detected by sensor 2.
```blocks
brick.buttonEnter.onEvent(ButtonEvent.Click, function () {
brick.showValue("color", sensors.color2.light(LightIntensityMode.Ambient), 1)
})
```
## See also
[show number](/reference/brick/show-number)

331
docs/static/download/connect.svg vendored Normal file
View File

@ -0,0 +1,331 @@
<svg xmlns="http://www.w3.org/2000/svg" width="261.3" height="109.3" viewBox="0 0 69.1 28.9" id="svg9461">
<defs id="defs9455">
<clipPath id="clipPath8689">
<path d="M0 1145.9h1366V0H0z" id="path8687"/>
</clipPath>
<clipPath id="clipPath8663">
<path d="M309.8 89.4h3.7v3.7h-3.7z" id="path8661"/>
</clipPath>
<clipPath id="clipPath8647">
<path d="M0 1145.9h1366V0H0z" id="path8645"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 .6661 -.32488 0 300.7 115)" id="linearGradient8637">
<stop offset="0" id="stop8633" stop-color="#757575"/>
<stop offset="1" id="stop8635" stop-color="#393939"/>
</linearGradient>
<clipPath id="clipPath8595">
<path d="M0 1145.9h1366V0H0z" id="path8593"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 12.8096 -17.18704 0 300.7 98.4)" id="linearGradient8585">
<stop offset="0" id="stop8579" stop-color="#6a6a6a"/>
<stop offset=".5" id="stop8581" stop-color="#48e400"/>
<stop offset="1" id="stop8583" stop-color="#6a6a6a"/>
</linearGradient>
<clipPath id="clipPath8561">
<path d="M0 1145.9h1366V0H0z" id="path8559"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -1.33016 5.597 0 300.7 88.4)" id="linearGradient8551">
<stop offset="0" id="stop8547" stop-color="#a9aba9"/>
<stop offset="1" id="stop8549" stop-color="#535453"/>
</linearGradient>
<clipPath id="clipPath8525">
<path d="M0 1145.9h1366V0H0z" id="path8523"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -.56074 .70884 0 300.7 115.6)" id="linearGradient8515">
<stop offset="0" id="stop8511" stop-color="#a9aba9"/>
<stop offset="1" id="stop8513" stop-color="#818181"/>
</linearGradient>
<clipPath id="clipPath8493">
<path d="M0 1145.9h1366V0H0z" id="path8491"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -2.39765 2.48247 0 300.7 98.1)" id="linearGradient8483">
<stop offset="0" id="stop8479" stop-color="#f2f2f2"/>
<stop offset="1" id="stop8481" stop-color="#7a7a7a"/>
</linearGradient>
<clipPath id="clipPath8449">
<path d="M0 1145.9h1366V0H0z" id="path8447"/>
</clipPath>
<clipPath id="clipPath8977">
<path d="M0 1145.9h1366V0H0z" id="path8975"/>
</clipPath>
<clipPath id="clipPath8951">
<path d="M593 101h3.6v3.7H593z" id="path8949"/>
</clipPath>
<clipPath id="clipPath8935">
<path d="M0 1145.9h1366V0H0z" id="path8933"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 .67046 -.32706 0 583.8 126.8)" id="linearGradient8925">
<stop offset="0" id="stop8921" stop-color="#757575"/>
<stop offset="1" id="stop8923" stop-color="#393939"/>
</linearGradient>
<clipPath id="clipPath8883">
<path d="M0 1145.9h1366V0H0z" id="path8881"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 12.89405 -17.29507 0 583.7 110)" id="linearGradient8873">
<stop offset="0" id="stop8867" stop-color="#6a6a6a"/>
<stop offset=".5" id="stop8869" stop-color="#48e400"/>
<stop offset="1" id="stop8871" stop-color="#6a6a6a"/>
</linearGradient>
<clipPath id="clipPath8849">
<path d="M0 1145.9h1366V0H0z" id="path8847"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -1.33884 5.6329 0 583.7 100)" id="linearGradient8839">
<stop offset="0" id="stop8835" stop-color="#a9aba9"/>
<stop offset="1" id="stop8837" stop-color="#535453"/>
</linearGradient>
<clipPath id="clipPath8813">
<path d="M0 1145.9h1366V0H0z" id="path8811"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -.56429 .71345 0 583.7 127.4)" id="linearGradient8803">
<stop offset="0" id="stop8799" stop-color="#a9aba9"/>
<stop offset="1" id="stop8801" stop-color="#818181"/>
</linearGradient>
<clipPath id="clipPath8781">
<path d="M0 1145.9h1366V0H0z" id="path8779"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -2.41323 2.4988 0 583.7 109.8)" id="linearGradient8771">
<stop offset="0" id="stop8767" stop-color="#f2f2f2"/>
<stop offset="1" id="stop8769" stop-color="#7a7a7a"/>
</linearGradient>
<clipPath id="clipPath8737">
<path d="M0 1145.9h1366V0H0z" id="path8735"/>
</clipPath>
<clipPath id="clipPath9285">
<path d="M0 1145.9h1366V0H0z" id="path9283"/>
</clipPath>
<clipPath id="clipPath9259">
<path d="M852.5 96.3h3.3v3.3h-3.3z" id="path9257"/>
</clipPath>
<clipPath id="clipPath9243">
<path d="M0 1145.9h1366V0H0z" id="path9241"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 .61565 -.3002 0 844 120)" id="linearGradient9233">
<stop offset="0" id="stop9229" stop-color="#757575"/>
<stop offset="1" id="stop9231" stop-color="#393939"/>
</linearGradient>
<clipPath id="clipPath9191">
<path d="M0 1145.9h1366V0H0z" id="path9189"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 11.84237 -15.8829 0 844 104.6)" id="linearGradient9181">
<stop offset="0" id="stop9175" stop-color="#6a6a6a"/>
<stop offset=".5" id="stop9177" stop-color="#48e400"/>
<stop offset="1" id="stop9179" stop-color="#6a6a6a"/>
</linearGradient>
<clipPath id="clipPath9157">
<path d="M0 1145.9h1366V0H0z" id="path9155"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -1.22922 5.1724 0 844 95.3)" id="linearGradient9147">
<stop offset="0" id="stop9143" stop-color="#a9aba9"/>
<stop offset="1" id="stop9145" stop-color="#535453"/>
</linearGradient>
<clipPath id="clipPath9121">
<path d="M0 1145.9h1366V0H0z" id="path9119"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -.51809 .65506 0 844 120.5)" id="linearGradient9111">
<stop offset="0" id="stop9107" stop-color="#a9aba9"/>
<stop offset="1" id="stop9109" stop-color="#818181"/>
</linearGradient>
<clipPath id="clipPath9089">
<path d="M0 1145.9h1366V0H0z" id="path9087"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -2.21578 2.29436 0 844 104.3)" id="linearGradient9079">
<stop offset="0" id="stop9075" stop-color="#f2f2f2"/>
<stop offset="1" id="stop9077" stop-color="#7a7a7a"/>
</linearGradient>
<clipPath id="clipPath9009">
<path d="M0 1145.9h1366V0H0z" id="path9007"/>
</clipPath>
<clipPath id="clipPath9041">
<path d="M779.5 134.7h16.7v-12.6h-16.7z" id="path9039"/>
</clipPath>
<clipPath id="clipPath9045">
<path d="M779.5 134.7h16.7v-12.6h-16.7z" id="path9043"/>
</clipPath>
<clipPath id="clipPath8907">
<path d="M0 1145.9h1366V0H0z" id="path8905"/>
</clipPath>
<clipPath id="clipPath8881">
<path d="M309.8 89.4h3.7v3.7h-3.7z" id="path8879"/>
</clipPath>
<clipPath id="clipPath8865">
<path d="M0 1145.9h1366V0H0z" id="path8863"/>
</clipPath>
<clipPath id="clipPath8813-1">
<path d="M0 1145.9h1366V0H0z" id="path8811-4"/>
</clipPath>
<clipPath id="clipPath8779">
<path d="M0 1145.9h1366V0H0z" id="path8777"/>
</clipPath>
<clipPath id="clipPath8743">
<path d="M0 1145.9h1366V0H0z" id="path8741"/>
</clipPath>
<clipPath id="clipPath8711">
<path d="M0 1145.9h1366V0H0z" id="path8709"/>
</clipPath>
<clipPath id="clipPath8667">
<path d="M0 1145.9h1366V0H0z" id="path8665"/>
</clipPath>
</defs>
<g id="layer1" transform="translate(0 -268)">
<g id="g11329" transform="matrix(.35278 0 0 -.35278 -42.7 327.3)">
<g id="g8661">
<g clip-path="url(#clipPath8667)" id="g8663">
<g transform="translate(134 148)" id="g8669">
<path id="path8671" d="M0 0h83a4 4 0 0 0 4-4v-52.5H-4V-4a4 4 0 0 0 4 4" fill="#e6e6e6"/>
</g>
<g transform="translate(134 146.5)" id="g8673">
<path id="path8675" d="M0 0h83c1.3 0 2.4-1.1 2.4-2.5V-52c0-.9-.6-1.5-1.5-1.5H-1c-.8 0-1.5.6-1.5 1.5v49.5C-2.5-1.1-1.4 0 0 0z" fill="none" stroke="#282828" stroke-width="3"/>
</g>
<g transform="translate(121 91)" id="g8677">
<path id="path8679" d="M0 0h108.8v-1.2a3 3 0 0 0-3-3H3a3 3 0 0 0-3 3z" fill="#626262"/>
</g>
<g transform="translate(165.8 91)" id="g8681">
<path id="path8683" d="M0 0h19.3c0-.8-.6-1.4-1.4-1.4H1.4C.6-1.4 0-.8 0 0" fill="#818181"/>
</g>
</g>
</g>
<g id="g8685">
<g id="g8687">
<g id="g8693">
<g id="g8695">
<path id="path8703" d="M285 127.8a.6.6 0 0 1-.7-.5V96.9c0-.3.3-.6.6-.6h31.5c.3 0 .6.3.6.6v30.4c0 .3-.3.5-.6.5z" fill="url(#linearGradient8483)"/>
</g>
</g>
</g>
</g>
<g id="g8705">
<g clip-path="url(#clipPath8711)" id="g8707">
<g transform="translate(286.8 99.6)" id="g8713">
<path id="path8715" d="M0 0h27.8c.4 0 .6-.3.6-.6v-11.3c0-.4-.2-.6-.6-.6H0c-.3 0-.6.2-.6.6V-.6c0 .3.3.6.6.6" fill="#f2f2f2"/>
</g>
</g>
</g>
<g id="g8717">
<g id="g8719">
<g id="g8725">
<g id="g8727">
<path id="path8735-5" d="M286.5 137.2a.6.6 0 0 1-.6-.6v-22.2c0-.3.3-.6.6-.6h28.4c.3 0 .5.3.5.6v22.2c0 .3-.2.6-.5.6z" fill="url(#linearGradient8515)"/>
</g>
</g>
</g>
</g>
<g id="g8737">
<g clip-path="url(#clipPath8743)" id="g8739">
<g transform="translate(289.7 134.1)" id="g8745">
<path id="path8747" d="M0 0h22c.6 0 1-.5 1-1.1v-12.4c0-.6-.4-1-1-1H0c-.6 0-1.1.4-1.1 1V-1c0 .5.5 1 1.1 1" fill="#393939"/>
</g>
<g transform="translate(291.4 133.5)" id="g8749">
<path id="path8751" d="M0 0h18.7c.4 0 .8-.4.8-.8v-11.9c0-.4-.4-.8-.8-.8H0c-.4 0-.8.3-.8.8V-.8c0 .4.4.8.8.8" fill="#98b6a7"/>
</g>
</g>
</g>
<g id="g8753">
<g id="g8755">
<g id="g8761">
<g id="g8763">
<path id="path8771" d="M286.2 94v-6.4c0-.3.2-.6.6-.6h27.8c.3 0 .6.3.6.6V94z" fill="url(#linearGradient8551)"/>
</g>
</g>
</g>
</g>
<g id="g8773">
<g clip-path="url(#clipPath8779)" id="g8775">
<g transform="translate(298.7 97.7)" id="g8781">
<path id="path8783" d="M0 0l-4.2 4.2v.5h-1a2.4 2.4 0 0 0 0 5h1v.5L0 14.4h4l4.2-4.2v-.6h1a2.4 2.4 0 1 0 0-4.9h-1v-.5L4.2 0z" fill="#6a6a6a"/>
</g>
</g>
</g>
<g id="g8785">
<g id="g8787">
<g id="g8793">
<g id="g8795">
<path id="path8805" d="M298.7 112.1l-4.2-4.3v-.5h-1c-1.4 0-2.5-1-2.5-2.4s1.1-2.5 2.5-2.5h1v-.5l4.2-4.2h4.2l4 4.2v.5h1c1.4 0 2.5 1.1 2.5 2.5 0 1.3-1.1 2.4-2.5 2.4h-1v.6l-4 4.2z" fill="url(#linearGradient8585)"/>
</g>
</g>
</g>
</g>
<g id="g8807">
<g clip-path="url(#clipPath8813-1)" id="g8809">
<g transform="translate(293.4 106.7)" id="g8815">
<path id="path8817" d="M0 0h3v-3.6H0c-1 0-1.8.8-1.8 1.8S-1 0 0 0" fill="#a9aba9"/>
</g>
<g transform="translate(308 103.1)" id="g8819">
<path id="path8821" d="M0 0h-3v3.6h3c1 0 1.8-.8 1.8-1.8S1 0 0 0" fill="#a9aba9"/>
</g>
<g transform="translate(299 106.7)" id="g8823">
<path id="path8825" d="M0 0h3.5l.2-.1v-3.4l-.2-.1H0l-.1.1V0H0" fill="#393939"/>
</g>
<g transform="translate(298.8 111.4)" id="g8827">
<path id="path8829" d="M0 0h3.8l2.8-2.9L5.4-4v-2.1h-1V-5c0 .5-.5.9-1 .9H.2a.7.7 0 0 1-.8-.8V-6h-1v2l-1.2 1.2z" fill="#a9aba9"/>
</g>
<g transform="translate(302.6 98.4)" id="g8831">
<path id="path8833" d="M0 0h-3.7l-2.9 2.9L-5.4 4v2.1h1V5c0-.5.5-.9 1-.9h3.2c.4 0 .8.4.8.8v1.3h1v-2L2.8 3z" fill="#a9aba9"/>
</g>
<path id="path8835" d="M300.3 119.6h.9v-4.1h-1z" fill="#393939"/>
<path id="path8837" d="M300.3 115.7h.9v-1.8h-1z" fill="#9b9b9b"/>
</g>
</g>
<g id="g8839">
<g id="g8841">
<g id="g8847">
<g id="g8849">
<path id="path8857" d="M300.3 113.8h.9v1.9h-1z" fill="url(#linearGradient8637)"/>
</g>
</g>
</g>
</g>
<g id="g8859">
<g clip-path="url(#clipPath8865)" id="g8861">
<path id="path8867" d="M300.3 113.8h.9v-1.7h-1z" fill="#818181"/>
<g transform="translate(288.2 113.8)" id="g8869">
<path id="path8871" d="M0 0h7v-1.7L5.2-3.4H.6c-.3 0-.6.2-.6.5z" fill="#a9aba9"/>
</g>
<path id="path8873" d="M309.9 93h3.6v-3.6h-3.6z" fill="#fff"/>
</g>
</g>
<g id="g8875">
<g clip-path="url(#clipPath8881)" id="g8877">
<g transform="translate(313.2 91.6)" id="g8883">
<path id="path8885" d="M0 0v-.3C-.3-.7-.4-1-.8-1l-.3.2v.1a.6.6 0 0 0-.5-.3c-.1 0-.2 0-.3.2l-.4-.1h-.6c-.2 0-.3 0-.3.2l.3 1h.4V0l.1.1.5.2.3-.1h.3c.2.1.3 0 .4 0V.1l.4.2.3-.1L0 0m-3.4-2.1H.2v3.6h-3.6z" fill="#fe0"/>
</g>
<g transform="translate(313.3 91.4)" id="g8887">
<path id="path8889" d="M0 0c0-.2 0-.3-.2-.5 0-.2-.3-.4-.6-.4l-.4.1a.7.7 0 0 0-.4-.1H-2a.6.6 0 0 0-.4 0H-3c-.3 0-.4.1-.4.3 0 .4.1.7.3 1 0 .2.2.2.4.2h2.1L0 .5V0m-3.5-2H.1v3.6h-3.6z" fill="#d52715"/>
</g>
<path id="path8891" d="M313.4 89.5H310V93h3.5zm-3.6 0h3.7V93h-3.7z" fill="#171714"/>
<g transform="translate(313.3 92)" id="g8893">
<path id="path8895" d="M0 0v-.2.2m0 0v-.2.1m0 0zm0 0z" fill="#171714"/>
</g>
<g transform="translate(312.9 91.6)" id="g8897">
<path id="path8899" d="M0 0l-.2-.5v-.1h-.1c0 .2 0 .4.2.6H0m.3-.2L0-.6C0-.8-.2-1-.3-1c-.2 0-.3 0-.3.3l.1.5c.1.2.2.4.5.4s.3-.3.3-.5M-1 .1V0l-.3-.5.1-.1.2.2c0 .2 0 .2.2.2s.2-.1.1-.2c0-.3-.2-.5-.5-.5a.3.3 0 0 0-.2.3v.5c.2.2.3.4.6.4.2 0 .3 0 .3-.2 0-.1 0-.2-.2-.2h-.1v.2m-1-.5v-.2h.3c0-.2-.2-.3-.3-.3-.2 0-.3.1-.3.2 0 .3 0 .5.2.7 0 .2.2.3.4.3l.2-.1c0-.1 0-.2-.2-.2h-.1v-.1c.1 0 .2 0 .1-.2h-.3m-.6-.3h.2c0-.2-.1-.3-.3-.3 0 0-.2 0-.2.2l.3.9s.1.1.2 0h.1c0-.3-.1-.5-.3-.8M0 .4C-.2.4-.3.4-.4.2l-.4.2-.4-.1-.3.1c-.2 0-.3 0-.4-.2v.1l-.3.1s-.2 0-.3-.2l-.3-.9c0-.2.1-.3.3-.3l.4.1h.9l.5.1.4-.2c.3 0 .5.3.6.7V0a.4.4 0 0 1-.3.4" fill="#171714"/>
</g>
</g>
</g>
<g id="g8901">
<g clip-path="url(#clipPath8907)" id="g8903">
<g transform="translate(295 91.5)" id="g8909">
<path id="path8911" d="M0 0v-.3h-.6l-.1-.1v-.4H0v-.4h-1l-.2.1h-.3l-.1-.1v-.5l.1-.1H.6V.5h-2.2v-.6h.5V0H0z" fill="#f2f2f2"/>
</g>
<g transform="translate(293 92)" id="g8913">
<path id="path8915" d="M0 0h-.5l-.1-.1-.6-1.3L-2 0h-.6v-.1l.9-2 .2-.1h.4l.1.1 1 2V0" fill="#f2f2f2"/>
</g>
<g transform="translate(290 91.1)" id="g8917">
<path id="path8919" d="M0 0h.1v-.4L0-.5h-1.5v-.3H0L.1-1v-.4h-2.2v2c0 .1 0 .2.1.1H.1V.4h-1.6V0z" fill="#f2f2f2"/>
</g>
<path id="path8921" d="M249 87h-13v7.9h13z" fill="#a9aba9"/>
<path id="path8923" d="M263.5 87h-12.9v7.9h12.9z"/>
<path id="path8925" d="M240.7 92.2h-1.3v1.4h1.3z"/>
<path id="path8927" d="M240.7 88.2h-1.3v1.4h1.3z"/>
<path id="path8929" d="M258.2 86h-14.5v9.9h14.5z"/>
<path id="path8931" d="M311.6 141h-5v9h5z" fill="#a9aba9"/>
<path id="path8933-4" d="M311.2 151.6h-4v9.3h4z"/>
<path id="path8935" d="M311.2 141.4h-.3v3h.3z"/>
<path id="path8937" d="M307.3 141.4h-.4v3h.4z"/>
<path id="path8939" d="M312.9 145h-7.3v12.2h7.3z"/>
<g transform="translate(309.2 158)" id="g8941">
<path id="path8943" d="M0 0v8.8h-36.4v-75.5h-15.1" fill="none" stroke="#000" stroke-width="2"/>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

252
docs/static/download/firmware.svg vendored Normal file
View File

@ -0,0 +1,252 @@
<svg xmlns="http://www.w3.org/2000/svg" width="261.3" height="109.3" viewBox="0 0 69.1 28.9" id="svg9461">
<defs id="defs9455">
<clipPath id="clipPath8689">
<path d="M0 1145.9h1366V0H0z" id="path8687"/>
</clipPath>
<clipPath id="clipPath8663">
<path d="M309.8 89.4h3.7v3.7h-3.7z" id="path8661"/>
</clipPath>
<clipPath id="clipPath8647">
<path d="M0 1145.9h1366V0H0z" id="path8645"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 .6661 -.32488 0 300.7 115)" id="linearGradient8637">
<stop offset="0" id="stop8633" stop-color="#757575"/>
<stop offset="1" id="stop8635" stop-color="#393939"/>
</linearGradient>
<clipPath id="clipPath8595">
<path d="M0 1145.9h1366V0H0z" id="path8593"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 12.8096 -17.18704 0 300.7 98.4)" id="linearGradient8585">
<stop offset="0" id="stop8579" stop-color="#6a6a6a"/>
<stop offset=".5" id="stop8581" stop-color="#48e400"/>
<stop offset="1" id="stop8583" stop-color="#6a6a6a"/>
</linearGradient>
<clipPath id="clipPath8561">
<path d="M0 1145.9h1366V0H0z" id="path8559"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -1.33016 5.597 0 300.7 88.4)" id="linearGradient8551">
<stop offset="0" id="stop8547" stop-color="#a9aba9"/>
<stop offset="1" id="stop8549" stop-color="#535453"/>
</linearGradient>
<clipPath id="clipPath8525">
<path d="M0 1145.9h1366V0H0z" id="path8523"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -.56074 .70884 0 300.7 115.6)" id="linearGradient8515">
<stop offset="0" id="stop8511" stop-color="#a9aba9"/>
<stop offset="1" id="stop8513" stop-color="#818181"/>
</linearGradient>
<clipPath id="clipPath8493">
<path d="M0 1145.9h1366V0H0z" id="path8491"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -2.39765 2.48247 0 300.7 98.1)" id="linearGradient8483">
<stop offset="0" id="stop8479" stop-color="#f2f2f2"/>
<stop offset="1" id="stop8481" stop-color="#7a7a7a"/>
</linearGradient>
<clipPath id="clipPath8449">
<path d="M0 1145.9h1366V0H0z" id="path8447"/>
</clipPath>
<clipPath id="clipPath8977">
<path d="M0 1145.9h1366V0H0z" id="path8975"/>
</clipPath>
<clipPath id="clipPath8951">
<path d="M593 101h3.6v3.7H593z" id="path8949"/>
</clipPath>
<clipPath id="clipPath8935">
<path d="M0 1145.9h1366V0H0z" id="path8933"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 .67046 -.32706 0 583.8 126.8)" id="linearGradient8925">
<stop offset="0" id="stop8921" stop-color="#757575"/>
<stop offset="1" id="stop8923" stop-color="#393939"/>
</linearGradient>
<clipPath id="clipPath8883">
<path d="M0 1145.9h1366V0H0z" id="path8881"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 12.89405 -17.29507 0 583.7 110)" id="linearGradient8873">
<stop offset="0" id="stop8867" stop-color="#6a6a6a"/>
<stop offset=".5" id="stop8869" stop-color="#48e400"/>
<stop offset="1" id="stop8871" stop-color="#6a6a6a"/>
</linearGradient>
<clipPath id="clipPath8849">
<path d="M0 1145.9h1366V0H0z" id="path8847"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -1.33884 5.6329 0 583.7 100)" id="linearGradient8839">
<stop offset="0" id="stop8835" stop-color="#a9aba9"/>
<stop offset="1" id="stop8837" stop-color="#535453"/>
</linearGradient>
<clipPath id="clipPath8813">
<path d="M0 1145.9h1366V0H0z" id="path8811"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -.56429 .71345 0 583.7 127.4)" id="linearGradient8803">
<stop offset="0" id="stop8799" stop-color="#a9aba9"/>
<stop offset="1" id="stop8801" stop-color="#818181"/>
</linearGradient>
<clipPath id="clipPath8781">
<path d="M0 1145.9h1366V0H0z" id="path8779"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -2.41323 2.4988 0 583.7 109.8)" id="linearGradient8771">
<stop offset="0" id="stop8767" stop-color="#f2f2f2"/>
<stop offset="1" id="stop8769" stop-color="#7a7a7a"/>
</linearGradient>
<clipPath id="clipPath8737">
<path d="M0 1145.9h1366V0H0z" id="path8735"/>
</clipPath>
</defs>
<g id="layer1" transform="translate(0 -268)">
<g id="g10860" transform="translate(-20.8 -2)">
<g transform="matrix(.35278 0 0 -.35278 62.8 291.4)" id="g8727">
<path id="path8729" d="M0 0h24" fill="none" stroke="#000" stroke-width="2"/>
</g>
<g id="g8731" transform="matrix(.35278 0 0 -.35278 -129 330.1)">
<g clip-path="url(#clipPath8737)" id="g8733">
<g transform="translate(458 159.9)" id="g8739">
<path id="path8741" d="M0 0h83a4 4 0 0 0 4-4v-52.5H-4V-4a4 4 0 0 0 4 4" fill="#e6e6e6"/>
</g>
<g transform="translate(458 158.4)" id="g8743">
<path id="path8745" d="M0 0h83c1.3 0 2.4-1.1 2.4-2.5V-52c0-.9-.6-1.5-1.5-1.5H-1c-.8 0-1.5.6-1.5 1.5v49.5C-2.5-1.1-1.4 0 0 0z" fill="none" stroke="#282828" stroke-width="3"/>
</g>
<g transform="translate(445 102.9)" id="g8747">
<path id="path8749" d="M0 0h108.8v-1.2a3 3 0 0 0-3-3H3a3 3 0 0 0-3 3z" fill="#626262"/>
</g>
<g transform="translate(489.8 102.9)" id="g8751">
<path id="path8753" d="M0 0h19.3c0-.8-.6-1.4-1.4-1.4H1.4C.6-1.4 0-.8 0 0" fill="#818181"/>
</g>
</g>
</g>
<g id="g8755" transform="matrix(.35278 0 0 -.35278 -129 330.1)">
<g id="g8757">
<g id="g8763">
<g id="g8765">
<path id="path8773" d="M567.9 139.7a.6.6 0 0 1-.6-.6v-30.6c0-.3.2-.6.6-.6h31.7c.3 0 .5.3.5.6v30.6c0 .3-.2.6-.5.6z" fill="url(#linearGradient8771)"/>
</g>
</g>
</g>
</g>
<g id="g8775" transform="matrix(.35278 0 0 -.35278 -129 330.1)">
<g clip-path="url(#clipPath8781)" id="g8777">
<g transform="translate(569.7 111.2)" id="g8783">
<path id="path8785" d="M0 0h28c.3 0 .6-.3.6-.6V-12c0-.4-.3-.6-.6-.6H0c-.3 0-.6.2-.6.6V-.6c0 .3.3.6.6.6" fill="#f2f2f2"/>
</g>
</g>
</g>
<g id="g8787" transform="matrix(.35278 0 0 -.35278 -129 330.1)">
<g id="g8789">
<g id="g8795">
<g id="g8797">
<path id="path8805" d="M569.4 149.1a.6.6 0 0 1-.6-.6v-22.3c0-.3.3-.6.6-.6H598c.3 0 .6.3.6.6v22.3c0 .3-.3.6-.6.6z" fill="url(#linearGradient8803)"/>
</g>
</g>
</g>
</g>
<g id="g8807" transform="matrix(.35278 0 0 -.35278 -129 330.1)">
<g clip-path="url(#clipPath8813)" id="g8809">
<g transform="translate(572.7 146)" id="g8815">
<path id="path8817" d="M0 0h22.1c.6 0 1.1-.5 1.1-1.1v-12.5c0-.6-.5-1-1-1H0c-.6 0-1.1.4-1.1 1V-1c0 .5.5 1 1.1 1" fill="#393939"/>
</g>
<g transform="translate(574.4 145.4)" id="g8819">
<path id="path8821" d="M0 0h18.8c.4 0 .8-.4.8-.8v-12c0-.4-.4-.8-.8-.8H0c-.4 0-.8.4-.8.8v12c0 .4.4.8.8.8" fill="#98b6a7"/>
</g>
</g>
</g>
<g id="g8823" transform="matrix(.35278 0 0 -.35278 -129 330.1)">
<g id="g8825">
<g id="g8831">
<g id="g8833">
<path id="path8841" d="M569.1 105.6v-6.4c0-.3.3-.6.6-.6h28c.3 0 .6.3.6.6v6.4z" fill="url(#linearGradient8839)"/>
</g>
</g>
</g>
</g>
<g id="g8843" transform="matrix(.35278 0 0 -.35278 -129 330.1)">
<g clip-path="url(#clipPath8849)" id="g8845">
<g transform="translate(581.7 109.3)" id="g8851">
<path id="path8853" d="M0 0l-4.2 4.2v.6h-1a2.5 2.5 0 0 0 0 4.9h1v.5L0 14.5h4l4.2-4.2v-.6h1a2.5 2.5 0 0 0 0-5h-1v-.5L4.2 0z" fill="#6a6a6a"/>
</g>
</g>
</g>
<g id="g8855" transform="matrix(.35278 0 0 -.35278 -129 330.1)">
<g id="g8857">
<g id="g8863">
<g id="g8865">
<path id="path8875" d="M581.7 123.8l-4.2-4.2v-.6h-1a2.5 2.5 0 1 1 0-5v.1h1v-.5l4.2-4.3h4.2l4.2 4.3v.5h1a2.5 2.5 0 0 1-.1 4.9h-1v.7l-4.1 4.1z" fill="url(#linearGradient8873)"/>
</g>
</g>
</g>
</g>
<g id="g8877" transform="matrix(.35278 0 0 -.35278 -129 330.1)">
<g clip-path="url(#clipPath8883)" id="g8879">
<g transform="translate(576.4 118.4)" id="g8885">
<path id="path8887" d="M0 0h3v-3.6H0A1.8 1.8 0 1 0 0 0" fill="#a9aba9"/>
</g>
<g transform="translate(591 114.8)" id="g8889">
<path id="path8891" d="M0 0h-3v3.6h3A1.8 1.8 0 1 0 0 0" fill="#a9aba9"/>
</g>
<g transform="translate(582 118.4)" id="g8893">
<path id="path8895" d="M0 0h3.6v-3.6H-.1V0H0" fill="#393939"/>
</g>
<g transform="translate(581.9 123.2)" id="g8897">
<path id="path8899" d="M0 0h3.8l2.8-2.9L5.5-4v-2H4.3v1c0 .5-.4 1-1 1h-3a.7.7 0 0 1-.8-.8v-1.4h-1V-4l-1.2 1.2z" fill="#a9aba9"/>
</g>
<g transform="translate(585.6 110)" id="g8901">
<path id="path8903" d="M0 0h-3.8l-2.8 2.9 1.2 1.2v2h1V5c0-.5.5-1 1-1h3.2c.5 0 .8.4.8.8v1.4h1.1V4l1.2-1.2z" fill="#a9aba9"/>
</g>
<path id="path8905" d="M583.3 131.4h.9v-4.1h-.9z" fill="#393939"/>
<path id="path8907" d="M583.3 127.4h.9v-1.8h-.9z" fill="#9b9b9b"/>
</g>
</g>
<g id="g8909" transform="matrix(.35278 0 0 -.35278 -129 330.1)">
<g id="g8911">
<g id="g8917">
<g id="g8919">
<path id="path8927" d="M583.3 125.6h.9v1.8h-.9z" fill="url(#linearGradient8925)"/>
</g>
</g>
</g>
</g>
<g id="g8929" transform="matrix(.35278 0 0 -.35278 -129 330.1)">
<g clip-path="url(#clipPath8935)" id="g8931">
<path id="path8937" d="M583.3 125.6h.9v-1.8h-.9z" fill="#818181"/>
<g transform="translate(571.2 125.6)" id="g8939">
<path id="path8941" d="M0 0h7v-1.7L5.3-3.5H.6c-.3 0-.6.3-.6.6z" fill="#a9aba9"/>
</g>
<path id="path8943" d="M593 104.7h3.6V101H593z" fill="#fff"/>
</g>
</g>
<g id="g8945" transform="matrix(.35278 0 0 -.35278 -129 330.1)">
<g clip-path="url(#clipPath8951)" id="g8947">
<g transform="translate(596.4 103.2)" id="g8953">
<path id="path8955" d="M0 0v-.3C-.3-.8-.4-1-.8-1l-.3.2a.6.6 0 0 0-.5-.2c-.1 0-.2 0-.3.2C-2-1-2.1-1-2.2-1h-.6a.3.3 0 0 0-.3.2l.3 1h.5l.5.2.2-.1h.4c.1.1.3 0 .4 0V.1l.4.2.3-.1L0 0m-3.4-2.1H.2v3.6h-3.6z" fill="#fe0"/>
</g>
<g transform="translate(596.5 103)" id="g8957">
<path id="path8959" d="M0 0c0-.2 0-.3-.2-.5 0-.2-.3-.4-.6-.4l-.4.1a.7.7 0 0 0-.4-.1H-2a.7.7 0 0 0-.4 0H-3c-.2 0-.3.1-.4.3 0 .4.2.7.4 1 0 .2.2.2.4.2h2.1L0 .5V0m-3.5-2H.1v3.6h-3.6z" fill="#d52715"/>
</g>
<path id="path8961" d="M596.6 101H593v3.6h3.6zm-3.7 0h3.7v3.7H593z" fill="#171714"/>
<g transform="translate(596.5 103.7)" id="g8963">
<path id="path8965" d="M0 0v-.2.2m0 0v-.2.1m0 0zm0 0z" fill="#171714"/>
</g>
<g transform="translate(596 103.2)" id="g8967">
<path id="path8969" d="M0 0a3 3 0 0 0-.2-.6h-.1c0 .2 0 .4.2.6H0m.3-.2L0-.6C0-.8-.2-1-.3-1c-.2 0-.3 0-.3.3l.1.4c.1.3.2.5.5.5s.3-.3.3-.5M-1 .1V0l-.3-.5.1-.1.2.2c0 .2 0 .2.2.2s.2-.1.1-.2c0-.3-.2-.5-.5-.5a.3.3 0 0 0-.3.3l.2.5c0 .2.2.4.5.4.2 0 .3 0 .3-.2 0-.1 0-.2-.2-.2h-.1v.2m-1-.5v-.2h.3c0-.2-.2-.3-.3-.3-.2 0-.3.1-.3.2 0 .3 0 .5.2.7 0 .2.2.3.4.3l.2-.1c0-.2 0-.2-.2-.2h-.1v-.1c.1 0 .2 0 .1-.2l-.3-.1m-.6-.2h.2c0-.2-.1-.3-.3-.3 0 0-.2 0-.2.2l.3.9s.1.1.2 0h.1c0-.3-.2-.5-.3-.8M0 .4C-.2.4-.3.4-.4.2l-.4.2-.4-.1-.3.1c-.2 0-.3 0-.4-.2v.1l-.3.1c-.1 0-.2 0-.3-.2-.1-.3-.3-.6-.3-1 0 0 .1-.2.3-.2l.3.1c.1 0 .2-.1.4 0h.6l.5.1.4-.2c.3 0 .5.3.6.6V0a.4.4 0 0 1-.3.4" fill="#171714"/>
</g>
</g>
</g>
<g id="g8971" transform="matrix(.35278 0 0 -.35278 -129 330.1)">
<g clip-path="url(#clipPath8977)" id="g8973">
<g transform="translate(578 103)" id="g8979">
<path id="path8981" d="M0 0v-.3h-.6l-.1-.1v-.4H0v-.4h-1l-.2.2h-.3l-.1-.1v-.6H.7V.5h-2.3v-.6h.5V0H0z" fill="#f2f2f2"/>
</g>
<g transform="translate(576 103.6)" id="g8983">
<path id="path8985" d="M0 0h-.5l-.1-.1-.6-1.3L-2-.1V0h-.5s-.1 0 0-.1l.9-2 .2-.1h.5l1 2L0 0" fill="#f2f2f2"/>
</g>
<g transform="translate(573 102.8)" id="g8987">
<path id="path8989" d="M0 0h.1v-.4L0-.5h-1.5v-.3H0L.1-1v-.4h-2.2v2l.1.2H.1V.4h-1.6V0z" fill="#f2f2f2"/>
</g>
<g transform="translate(583.5 136.6)" id="g8991">
<path id="path8993" d="M0 0l-.8 1.3-1.4-2.9 4-1c-.5.5-.5.7-.9 1.3.5.1 1 .4 1.4.7.8.4 1.5 1 2 1.9a4 4 0 0 1-.6 3.6c-.4 0-.8 0-1.3-.2C3.5 3 3.5 1 0 0" fill="#303030"/>
</g>
<g transform="translate(583.1 141.4)" id="g8995">
<path id="path8997" d="M0 0l.8-1.2 1.4 2.8-3.8 1 .7-1.3-1.3-.7a4.5 4.5 0 0 1-2-2c-.4-1-.2-2.4.5-3.4.4 0 .8 0 1.2.2C-3.3-3-3.3-1 0 0" fill="#303030"/>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

327
docs/static/download/transfer.svg vendored Normal file
View File

@ -0,0 +1,327 @@
<svg xmlns="http://www.w3.org/2000/svg" width="261.3" height="109.3" viewBox="0 0 69.1 28.9" id="svg9461">
<defs id="defs9455">
<clipPath id="clipPath8689">
<path d="M0 1145.9h1366V0H0z" id="path8687"/>
</clipPath>
<clipPath id="clipPath8663">
<path d="M309.8 89.4h3.7v3.7h-3.7z" id="path8661"/>
</clipPath>
<clipPath id="clipPath8647">
<path d="M0 1145.9h1366V0H0z" id="path8645"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 .6661 -.32488 0 300.7 115)" id="linearGradient8637">
<stop offset="0" id="stop8633" stop-color="#757575"/>
<stop offset="1" id="stop8635" stop-color="#393939"/>
</linearGradient>
<clipPath id="clipPath8595">
<path d="M0 1145.9h1366V0H0z" id="path8593"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 12.8096 -17.18704 0 300.7 98.4)" id="linearGradient8585">
<stop offset="0" id="stop8579" stop-color="#6a6a6a"/>
<stop offset=".5" id="stop8581" stop-color="#48e400"/>
<stop offset="1" id="stop8583" stop-color="#6a6a6a"/>
</linearGradient>
<clipPath id="clipPath8561">
<path d="M0 1145.9h1366V0H0z" id="path8559"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -1.33016 5.597 0 300.7 88.4)" id="linearGradient8551">
<stop offset="0" id="stop8547" stop-color="#a9aba9"/>
<stop offset="1" id="stop8549" stop-color="#535453"/>
</linearGradient>
<clipPath id="clipPath8525">
<path d="M0 1145.9h1366V0H0z" id="path8523"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -.56074 .70884 0 300.7 115.6)" id="linearGradient8515">
<stop offset="0" id="stop8511" stop-color="#a9aba9"/>
<stop offset="1" id="stop8513" stop-color="#818181"/>
</linearGradient>
<clipPath id="clipPath8493">
<path d="M0 1145.9h1366V0H0z" id="path8491"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -2.39765 2.48247 0 300.7 98.1)" id="linearGradient8483">
<stop offset="0" id="stop8479" stop-color="#f2f2f2"/>
<stop offset="1" id="stop8481" stop-color="#7a7a7a"/>
</linearGradient>
<clipPath id="clipPath8449">
<path d="M0 1145.9h1366V0H0z" id="path8447"/>
</clipPath>
<clipPath id="clipPath8977">
<path d="M0 1145.9h1366V0H0z" id="path8975"/>
</clipPath>
<clipPath id="clipPath8951">
<path d="M593 101h3.6v3.7H593z" id="path8949"/>
</clipPath>
<clipPath id="clipPath8935">
<path d="M0 1145.9h1366V0H0z" id="path8933"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 .67046 -.32706 0 583.8 126.8)" id="linearGradient8925">
<stop offset="0" id="stop8921" stop-color="#757575"/>
<stop offset="1" id="stop8923" stop-color="#393939"/>
</linearGradient>
<clipPath id="clipPath8883">
<path d="M0 1145.9h1366V0H0z" id="path8881"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 12.89405 -17.29507 0 583.7 110)" id="linearGradient8873">
<stop offset="0" id="stop8867" stop-color="#6a6a6a"/>
<stop offset=".5" id="stop8869" stop-color="#48e400"/>
<stop offset="1" id="stop8871" stop-color="#6a6a6a"/>
</linearGradient>
<clipPath id="clipPath8849">
<path d="M0 1145.9h1366V0H0z" id="path8847"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -1.33884 5.6329 0 583.7 100)" id="linearGradient8839">
<stop offset="0" id="stop8835" stop-color="#a9aba9"/>
<stop offset="1" id="stop8837" stop-color="#535453"/>
</linearGradient>
<clipPath id="clipPath8813">
<path d="M0 1145.9h1366V0H0z" id="path8811"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -.56429 .71345 0 583.7 127.4)" id="linearGradient8803">
<stop offset="0" id="stop8799" stop-color="#a9aba9"/>
<stop offset="1" id="stop8801" stop-color="#818181"/>
</linearGradient>
<clipPath id="clipPath8781">
<path d="M0 1145.9h1366V0H0z" id="path8779"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -2.41323 2.4988 0 583.7 109.8)" id="linearGradient8771">
<stop offset="0" id="stop8767" stop-color="#f2f2f2"/>
<stop offset="1" id="stop8769" stop-color="#7a7a7a"/>
</linearGradient>
<clipPath id="clipPath8737">
<path d="M0 1145.9h1366V0H0z" id="path8735"/>
</clipPath>
<clipPath id="clipPath9285">
<path d="M0 1145.9h1366V0H0z" id="path9283"/>
</clipPath>
<clipPath id="clipPath9259">
<path d="M852.5 96.3h3.3v3.3h-3.3z" id="path9257"/>
</clipPath>
<clipPath id="clipPath9243">
<path d="M0 1145.9h1366V0H0z" id="path9241"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 .61565 -.3002 0 844 120)" id="linearGradient9233">
<stop offset="0" id="stop9229" stop-color="#757575"/>
<stop offset="1" id="stop9231" stop-color="#393939"/>
</linearGradient>
<clipPath id="clipPath9191">
<path d="M0 1145.9h1366V0H0z" id="path9189"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 11.84237 -15.8829 0 844 104.6)" id="linearGradient9181">
<stop offset="0" id="stop9175" stop-color="#6a6a6a"/>
<stop offset=".5" id="stop9177" stop-color="#48e400"/>
<stop offset="1" id="stop9179" stop-color="#6a6a6a"/>
</linearGradient>
<clipPath id="clipPath9157">
<path d="M0 1145.9h1366V0H0z" id="path9155"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -1.22922 5.1724 0 844 95.3)" id="linearGradient9147">
<stop offset="0" id="stop9143" stop-color="#a9aba9"/>
<stop offset="1" id="stop9145" stop-color="#535453"/>
</linearGradient>
<clipPath id="clipPath9121">
<path d="M0 1145.9h1366V0H0z" id="path9119"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -.51809 .65506 0 844 120.5)" id="linearGradient9111">
<stop offset="0" id="stop9107" stop-color="#a9aba9"/>
<stop offset="1" id="stop9109" stop-color="#818181"/>
</linearGradient>
<clipPath id="clipPath9089">
<path d="M0 1145.9h1366V0H0z" id="path9087"/>
</clipPath>
<linearGradient x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -2.21578 2.29436 0 844 104.3)" id="linearGradient9079">
<stop offset="0" id="stop9075" stop-color="#f2f2f2"/>
<stop offset="1" id="stop9077" stop-color="#7a7a7a"/>
</linearGradient>
<clipPath id="clipPath9009">
<path d="M0 1145.9h1366V0H0z" id="path9007"/>
</clipPath>
<clipPath id="clipPath9041">
<path d="M779.5 134.7h16.7v-12.6h-16.7z" id="path9039"/>
</clipPath>
<clipPath id="clipPath9045">
<path d="M779.5 134.7h16.7v-12.6h-16.7z" id="path9043"/>
</clipPath>
</defs>
<g id="layer1" transform="translate(0 -268)">
<g id="g8999" transform="matrix(.35278 0 0 -.35278 40.2 289.4)">
<path d="M0 0h40" id="path9001" fill="none" stroke="#000" stroke-width="2"/>
</g>
<g id="g9011" transform="matrix(.35278 0 0 -.35278 10.4 271.7)">
<path d="M0 0h83a4 4 0 0 0 4-4v-52.5H-4V-4a4 4 0 0 0 4 4" id="path9013" fill="#e6e6e6"/>
</g>
<g id="g9015" transform="matrix(.35278 0 0 -.35278 10.4 272.3)">
<path d="M0 0h83c1.3 0 2.4-1.1 2.4-2.5V-52c0-.9-.6-1.5-1.5-1.5H-1c-.8 0-1.5.6-1.5 1.5v49.5C-2.5-1.1-1.4 0 0 0z" id="path9017" fill="none" stroke="#282828" stroke-width="3"/>
</g>
<g id="g9019" transform="matrix(.35278 0 0 -.35278 5.8 291.9)">
<path d="M0 0h108.8v-1.2a3 3 0 0 0-3-3H3a3 3 0 0 0-3 3z" id="path9021" fill="#626262"/>
</g>
<g id="g9023" transform="matrix(.35278 0 0 -.35278 21.6 291.9)">
<path d="M0 0h19.3c0-.8-.6-1.4-1.4-1.4H1.4C.6-1.4 0-.8 0 0" id="path9025" fill="#818181"/>
</g>
<g id="g9027" transform="matrix(.35278 0 0 -.35278 45 286.7)">
<path d="M0 0l-28-5.4-7.6 39 20 3.9c3.9-2.4 8-4.7 9.4-5.4z" id="path9029" fill="#fff"/>
</g>
<g id="g9031" transform="matrix(.35278 0 0 -.35278 45.4 287)">
<path d="M0 0l-30-5.8-8 41 21.5 4.1c4.7-2.8 10-5.7 10-5.7zm-2.3 1.6l-6 30.7c-1.6.8-5.2 2.8-8.6 4.9l-18.7-3.6 7.2-37 26 5" id="path9033" fill="#303030"/>
</g>
<g id="g9035" transform="matrix(.35278 0 0 -.35278 -239.7 326.4)">
<g id="g9061">
<g clip-path="url(#clipPath9041)" id="g9059">
<g id="g9057">
<g id="g9055">
<g clip-path="url(#clipPath9045)" id="g9053">
<g aria-label=".uf2" transform="scale(1 -1) rotate(-11 -255.3 -4117.6)" style="-inkscape-font-specification:LEGOChalet60-Bold" id="text9051" font-weight="700" font-size="9" font-family="LEGO Chalet 60" fill="#303030">
<path d="M2.4 0H.8v-1.7h1.6z" id="path12451"/>
<path d="M7.6 0H6.1v-.5l-.9.5-.8.1Q3.6.1 3-.3q-.4-.5-.4-1.4V-5h1.6v3l.1.4q0 .2.3.3h.9l.5-.2V-5h1.5z" id="path12453"/>
<path d="M11.1-5.7H9.7q-.2.2-.2.7h1.3v1.1H9.6V0H8v-3.9h-.7v-1H8v-.2q0-.9.5-1.3Q9-7 10-7h.6l.5.1z" id="path12455"/>
<path d="M16 0h-5.2v-1L12-2l1-.8q.5-.5.7-1 .2-.3.2-.7 0-.4-.3-.7-.3-.2-.8-.2l-.9.2-.8.4H11v-1.5l.9-.2 1.2-.2q1.2 0 1.9.5.6.6.6 1.5 0 .6-.3 1.2-.3.5-1 1.1l-.7.7-.6.4h3z" id="path12457"/>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
<g transform="matrix(.35278 0 0 -.35278 -239.7 326.4)" id="g9063">
<g id="g9065">
<g id="g9071">
<g id="g9073">
<path d="M829.4 131.8a.5.5 0 0 1-.5-.6v-28c0-.3.2-.6.5-.6h29.1c.3 0 .6.3.6.6v28c0 .3-.3.6-.6.6z" id="path9081" fill="url(#linearGradient9079)"/>
</g>
</g>
</g>
</g>
<g transform="matrix(.35278 0 0 -.35278 -239.7 326.4)" id="g9083">
<g id="g9085" clip-path="url(#clipPath9089)">
<g id="g9091" transform="translate(831.1 105.6)">
<path d="M0 0h25.7c.3 0 .6-.2.6-.5V-11c0-.3-.3-.6-.6-.6H0c-.3 0-.5.3-.5.6V-.5c0 .3.2.5.5.5" id="path9093" fill="#f2f2f2"/>
</g>
</g>
</g>
<g transform="matrix(.35278 0 0 -.35278 -239.7 326.4)" id="g9095">
<g id="g9097">
<g id="g9103">
<g id="g9105">
<path d="M830.9 140.4a.5.5 0 0 1-.6-.5v-20.5c0-.3.3-.6.6-.6H857c.3 0 .5.3.5.6v20.5c0 .3-.2.5-.5.5z" id="path9113" fill="url(#linearGradient9111)"/>
</g>
</g>
</g>
</g>
<g transform="matrix(.35278 0 0 -.35278 -239.7 326.4)" id="g9115">
<g id="g9117" clip-path="url(#clipPath9121)">
<g id="g9123" transform="translate(833.9 137.6)">
<path d="M0 0h20.3c.6 0 1-.5 1-1v-11.4c0-.6-.4-1-1-1H0a1 1 0 0 0-1 1V-1c0 .5.4 1 1 1" id="path9125" fill="#393939"/>
</g>
<g id="g9127" transform="translate(835.4 137)">
<path d="M0 0h17.2c.5 0 .8-.3.8-.7v-11c0-.5-.3-.8-.8-.8H0c-.4 0-.7.3-.7.8v11c0 .4.3.7.7.7" id="path9129" fill="#98b6a7"/>
</g>
</g>
</g>
<g transform="matrix(.35278 0 0 -.35278 -239.7 326.4)" id="g9131">
<g id="g9133">
<g id="g9139">
<g id="g9141">
<path d="M830.6 100.4v-5.8c0-.3.2-.5.5-.5h25.7c.3 0 .6.2.6.5v5.8z" id="path9149" fill="url(#linearGradient9147)"/>
</g>
</g>
</g>
</g>
<g transform="matrix(.35278 0 0 -.35278 -239.7 326.4)" id="g9151">
<g id="g9153" clip-path="url(#clipPath9157)">
<g id="g9159" transform="translate(842.2 103.9)">
<path d="M0 0l-3.9 3.9v.5h-1a2.3 2.3 0 1 0 0 4.5h1v.5l3.9 4h3.8c1.7-1.9 3.9-4 3.9-4V9h.8a2.3 2.3 0 0 0 0-4.5h-.8V4L3.8 0z" id="path9161" fill="#6a6a6a"/>
</g>
</g>
</g>
<g transform="matrix(.35278 0 0 -.35278 -239.7 326.4)" id="g9163">
<g id="g9165">
<g id="g9171">
<g id="g9173">
<path d="M842.1 117.2l-3.8-3.9v-.5h-1a2.3 2.3 0 1 1 0-4.5h1v-.5l3.9-3.9h3.8l3.8 3.9v.5h1c1.1 0 2 1 2.1 2.2 0 1.2-1 2.3-2.2 2.3h-.9v.6l-3.8 3.8z" id="path9183" fill="url(#linearGradient9181)"/>
</g>
</g>
</g>
</g>
<g transform="matrix(.35278 0 0 -.35278 -239.7 326.4)" id="g9185">
<g id="g9187" clip-path="url(#clipPath9191)">
<g id="g9193" transform="translate(837.3 112.3)">
<path d="M0 0h2.8v-3.4H0A1.7 1.7 0 0 0 0 0" id="path9195" fill="#a9aba9"/>
</g>
<g id="g9197" transform="translate(850.7 109)">
<path d="M0 0h-2.8v3.4H0A1.7 1.7 0 0 0 0 0" id="path9199" fill="#a9aba9"/>
</g>
<g id="g9201" transform="translate(842.4 112.3)">
<path d="M0 0h3.3v-3.3H-.1V0H0" id="path9203" fill="#393939"/>
</g>
<g id="g9205" transform="translate(842.3 116.6)">
<path d="M0 0h3.5L6-2.6 5-3.7v-2H4v1.2c0 .4-.4.8-.8.8h-3a.7.7 0 0 1-.7-.7v-1.3h-1v2l-1.1 1z" id="path9207" fill="#a9aba9"/>
</g>
<g id="g9209" transform="translate(845.8 104.6)">
<path d="M0 0h-3.5L-6 2.7l1.1 1v2h1V4.6c0-.5.4-.9.8-.9h3a.7.7 0 0 1 .8.7v1.3h1v-2l1-1z" id="path9211" fill="#a9aba9"/>
</g>
<path d="M843.6 124.1h.8v-3.7h-.8z" id="path9213" fill="#393939"/>
<path d="M843.6 120.5h.8V119h-.8z" id="path9215" fill="#9b9b9b"/>
</g>
</g>
<g transform="matrix(.35278 0 0 -.35278 -239.7 326.4)" id="g9217">
<g id="g9219">
<g id="g9225">
<g id="g9227">
<path d="M843.6 118.8h.8v1.7h-.8z" id="path9235" fill="url(#linearGradient9233)"/>
</g>
</g>
</g>
</g>
<g transform="matrix(.35278 0 0 -.35278 -239.7 326.4)" id="g9237">
<g id="g9239" clip-path="url(#clipPath9243)">
<path d="M843.6 118.8h.8v-1.6h-.8z" id="path9245" fill="#818181"/>
<g id="g9247" transform="translate(832.5 118.8)">
<path d="M0 0h6.5v-1.6L4.8-3.2H.5c-.3 0-.5.3-.5.6z" id="path9249" fill="#a9aba9"/>
</g>
<path d="M852.5 99.6h3.3v-3.3h-3.3z" id="path9251" fill="#fff"/>
</g>
</g>
<g transform="matrix(.35278 0 0 -.35278 -239.7 326.4)" id="g9253">
<g id="g9255" clip-path="url(#clipPath9259)">
<g id="g9261" transform="translate(855.6 98.2)">
<path d="M0 0v-.3C-.3-.7-.4-1-.7-1-.9-1-1-1-1-.8a.5.5 0 0 0-.5-.2l-.3.1h-.8l-.3.1c0 .4.2.6.3 1h.5l.4.2.3-.1h.6V.2h.1l.4.2.2-.1V0m-3-2H.2v3.4H-3z" id="path9263" fill="#fe0"/>
</g>
<g id="g9265" transform="translate(855.7 98.1)">
<path d="M0 0l-.1-.4C-.2-.7-.5-1-.7-1c-.2 0-.3 0-.4.2a.6.6 0 0 0-.4-.2l-.3.1a.6.6 0 0 0-.3 0h-.6c-.2 0-.4 0-.4.3l.3.9.4.2.2-.1.4.1h.6l.4-.1h.7L0 0m-3.2-1.8H.1v3.3h-3.3z" id="path9267" fill="#d52715"/>
</g>
<path d="M855.8 96.3h-3.3v3.3h3.3zm-3.3 0h3.3v3.3h-3.3z" id="path9269" fill="#171714"/>
<g id="g9271" transform="translate(855.7 98.7)">
<path d="M0 0v-.2.2m0 0v-.1m0 0zm0 0z" id="path9273" fill="#171714"/>
</g>
<g id="g9275" transform="translate(855.3 98.2)">
<path d="M0 0l-.2-.5h-.1c0 .2 0 .4.2.5H0m.2-.1L.1-.6l-.4-.2c-.1 0-.3 0-.3.2l.1.5c.1.2.2.4.5.4s.3-.3.2-.4m-1 .2l-.3-.6.2.1v.1l.1.1c.2 0 .2-.1.2-.2 0-.2-.2-.4-.5-.4-.1 0-.2 0-.2.2V0c.2.2.3.4.6.4.1 0 .2 0 .2-.2L-.6 0s-.2 0-.1.1m-1-.4v-.1h.3c0-.2-.2-.3-.3-.3-.1 0-.2 0-.3.2l.2.7.4.2.2-.1c0-.1 0-.2-.2-.2l-.2-.1.3-.1c0-.2-.2-.2-.3-.1m-.6-.2h.2c0-.3-.2-.3-.3-.3 0 0-.2 0-.2.2 0 .3.2.5.3.8h.2c0-.2 0-.5-.2-.7M0 .4C-.2.4-.3.4-.4.2c-.1.2-.2.2-.4.2L-1 .3l-.3.1c-.1 0-.3 0-.4-.2v.1h-.5l-.3-1s.1-.2.3-.2l.3.1.3-.1.3.1.3-.1c.2 0 .3 0 .4.2l.4-.2c.3 0 .5.2.6.6V0a.3.3 0 0 1-.3.4" id="path9277" fill="#171714"/>
</g>
</g>
</g>
<g transform="matrix(.35278 0 0 -.35278 -239.7 326.4)" id="g9279">
<g id="g9281" clip-path="url(#clipPath9285)">
<g id="g9287" transform="translate(838.7 98.2)">
<path d="M0 0v-.3h-.5l-.1-.1v-.4H0v-.3h-1v.2h-.4v-.6h2V.4h-2v-.5h.4V0h1z" id="path9289" fill="#f2f2f2"/>
</g>
<g id="g9291" transform="translate(836.9 98.7)">
<path d="M0 0h-.4l-.2-.1-.5-1.2-.6 1.2-.1.1h-.5v-.1l.8-1.8.2-.1h.5l.9 2H0" id="path9293" fill="#f2f2f2"/>
</g>
<g id="g9295" transform="translate(834.2 97.9)">
<path d="M0 0h.1v-.4h-1.5v-.4H0L.1-1v-.3H-2v2h2V.3h-1.5V0z" id="path9297" fill="#f2f2f2"/>
</g>
<g id="g9299" transform="translate(820.8 131.1)">
<path d="M0 0l-1.9-2.9 7.3-1C4.3 1.3 4 1.7 3.4 5.2l-2-3a39.5 39.5 0 0 1-4.1 3.2c-1.4.8-3 1.3-4.7 1.5-2.1 0-4.3-.2-6.4-.8l.1-3.3C-9 4.8-3.5 3.8 0 0" id="path9301" fill="#303030"/>
</g>
<g id="g9303" transform="translate(767 107.4)">
<path d="M0 0c1.6 2.3 3.8 4 6.4 5" id="path9305" fill="none" stroke="#303030"/>
</g>
<g id="g9307" transform="translate(766.2 110.4)">
<path d="M0 0c1.6 2.3 3.8 4 6.4 5" id="path9309" fill="none" stroke="#303030"/>
</g>
<g id="g9311" transform="translate(765.6 113.3)">
<path d="M0 0c1.6 2.3 3.8 4 6.4 5" id="path9313" fill="none" stroke="#303030"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

4
docs/static/filelogo.svg vendored Normal file
View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<path fill="#aa278f" d="M32 15.994v-.011c0-.108-.005-.209-.016-.303h-.001c-.032-.285-.112-.504-.239-.656-.171-.204-.459-.435-.864-.691a4.275 4.275 0 0 1-.986-.827c-.252-.296-.442-.734-.57-1.316-.049-.227-.087-.719-.112-1.473V8.696c0-.38-.031-.723-.076-1.049a12.313 12.313 0 0 0-.004-.188c-.009-.782-.18-1.475-.513-2.078a3.462 3.462 0 0 0-1.416-1.401c-.611-.33-1.305-.495-2.081-.495H6.271s-.674.067-.962.201a4.021 4.021 0 0 0-.521.295 3.502 3.502 0 0 0-.798.59c-.693.688-1.061 1.601-1.113 2.734a9.172 9.172 0 0 0-.088 1.283v2.558a6.802 6.802 0 0 1-.183 1.373 2.311 2.311 0 0 1-.532 1.033 2.67 2.67 0 0 0-.202.196c-.265.238-.638.511-1.13.823-.404.262-.64.633-.715 1.108l-.002.023a2.195 2.195 0 0 0-.023.287L0 16.006v.011c0 .108.005.209.016.303h.001c.032.285.112.504.239.656.171.204.459.435.864.691.406.256.735.532.986.827.252.296.442.734.57 1.316.049.227.087.719.112 1.473v2.019c0 .38.031.723.076 1.049l.004.188c.009.782.18 1.475.513 2.078a3.462 3.462 0 0 0 1.416 1.401c.611.33 1.305.495 2.081.495H25.73c.35 0 .673-.067.961-.201.184-.085.356-.187.521-.296.291-.159.559-.353.798-.59.693-.688 1.061-1.601 1.113-2.734.056-.398.088-.823.088-1.283v-2.558c.019-.495.079-.953.183-1.373.104-.419.282-.762.532-1.033a2.67 2.67 0 0 0 .202-.196c.265-.238.638-.511 1.13-.823.404-.262.64-.633.715-1.108h.002l.002-.023c.013-.092.022-.187.023-.287v-.014z"/>
<path fill="#fff" d="M27.366 16.522l.819-.518-.821-.516a4.547 4.547 0 0 1-.927-.744 3.033 3.033 0 0 1-.554-.896 5.166 5.166 0 0 1-.328-1.339 16.319 16.319 0 0 1-.103-1.961c0-.781-.016-1.365-.05-1.786-.039-.489-.123-.852-.258-1.112a1.36 1.36 0 0 0-.718-.661c-.223-.089-.527-.154-.924-.199a.532.532 0 0 1-.356-.213c-.11-.133-.165-.344-.165-.627 0-.41.086-.811 1.121-.811.636 0 1.196.127 1.666.376.464.247.818.589 1.085 1.046.267.458.406.995.413 1.597.064 3.554.129 4.265.184 4.492.153.63.382 1.109.701 1.464.287.319.635.602 1.035.843.29.175.501.341.627.493.035.043.116.181.116.554 0 .383-.12.628-.39.794-.606.373-1.041.699-1.331.997a2.734 2.734 0 0 0-.678 1.24c-.112.437-.177 1.05-.198 1.875-.02.773-.042 1.741-.066 2.904-.021.941-.306 1.668-.873 2.222-.568.554-1.317.823-2.291.823-.409 0-.71-.077-.895-.23-.155-.128-.226-.32-.226-.604 0-.179.03-.336.093-.479a.682.682 0 0 1 .188-.268.463.463 0 0 1 .24-.094c.414-.055.725-.127.951-.219.317-.131.567-.378.723-.716.124-.269.2-.625.233-1.089.029-.402.044-.968.044-1.725.016-1.061.077-1.896.182-2.481.095-.53.274-.987.533-1.359.261-.375.665-.736 1.198-1.073zm-16.618 6.519h10.458a.75.75 0 0 0 .751-.751l-.001-3.709c-.134-.449-.518-.492-.878-.15-.033 0-.393.443-1.22.443a2.033 2.033 0 0 1-1.944-1.715h-.011a6.59 6.59 0 0 1 0-.526h.011a2.03 2.03 0 0 1 1.944-1.715c.827 0 1.187.443 1.22.443.35.332.738.252.879-.147l.001-3.432a.769.769 0 0 0-.562-.741c-.061.016-3.259 0-3.259 0-.786.065-1.063-.466-.624-.928 0-.033.443-.393.443-1.22a2.033 2.033 0 0 0-1.715-1.944v-.011a6.59 6.59 0 0 0-.526 0v.011A2.03 2.03 0 0 0 14 8.893c0 .827.443 1.187.443 1.22.439.462.254.97-.624.928 0 0-3.198.016-3.259 0a.77.77 0 0 0-.562.741V22.29a.75.75 0 0 0 .75.751zm-6.197-3.692c.055.227.12.938.184 4.492.007.602.146 1.138.413 1.597.267.458.622.8 1.085 1.046.47.25 1.03.376 1.666.376 1.035 0 1.121-.4 1.121-.811 0-.283-.056-.493-.165-.627a.537.537 0 0 0-.356-.213c-.397-.045-.701-.11-.925-.199a1.367 1.367 0 0 1-.718-.661c-.135-.259-.219-.623-.258-1.112a24.159 24.159 0 0 1-.05-1.786c0-.751-.035-1.41-.103-1.961a5.174 5.174 0 0 0-.329-1.339 3.028 3.028 0 0 0-.554-.896 4.52 4.52 0 0 0-.927-.744l-.821-.516.819-.518c.533-.337.936-.698 1.199-1.075.259-.372.438-.829.533-1.359.105-.585.166-1.419.182-2.481 0-.757.014-1.323.044-1.725.033-.464.109-.82.233-1.089.156-.337.406-.584.723-.715.226-.092.537-.163.951-.219a.463.463 0 0 0 .24-.094.662.662 0 0 0 .189-.267 1.18 1.18 0 0 0 .093-.479c0-.284-.072-.476-.226-.604-.186-.153-.487-.23-.895-.23-.974 0-1.723.269-2.291.823-.567.554-.852 1.281-.873 2.222a588.806 588.806 0 0 1-.065 2.904c-.021.825-.086 1.438-.198 1.875a2.731 2.731 0 0 1-.679 1.24c-.289.298-.725.624-1.331.997-.27.166-.39.41-.39.794 0 .373.081.511.116.554.127.153.338.319.627.493.4.24.748.524 1.035.843.319.355.548.834.701 1.464z"/>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
docs/static/hero.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 585 KiB

View File

@ -8,7 +8,7 @@ import { FieldSpeed } from "./field_speed";
import { FieldBrickButtons } from "./field_brickbuttons"; import { FieldBrickButtons } from "./field_brickbuttons";
import { FieldTurnRatio } from "./field_turnratio"; import { FieldTurnRatio } from "./field_turnratio";
pxt.editor.initExtensionsAsync = function(opts: pxt.editor.ExtensionOptions): Promise<pxt.editor.ExtensionResult> { pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): Promise<pxt.editor.ExtensionResult> {
pxt.debug('loading pxt-ev3 target extensions...') pxt.debug('loading pxt-ev3 target extensions...')
updateBlocklyShape(); updateBlocklyShape();
const res: pxt.editor.ExtensionResult = { const res: pxt.editor.ExtensionResult = {
@ -28,7 +28,95 @@ pxt.editor.initExtensionsAsync = function(opts: pxt.editor.ExtensionOptions): Pr
selector: "turnratio", selector: "turnratio",
editor: FieldTurnRatio editor: FieldTurnRatio
}], }],
deployCoreAsync deployCoreAsync,
showUploadInstructionsAsync: (fn: string, url: string, confirmAsync: (options: any) => Promise<number>) => {
let resolve: (thenableOrResult?: void | PromiseLike<void>) => void;
let reject: (error: any) => void;
const deferred = new Promise<void>((res, rej) => {
resolve = res;
reject = rej;
});
const boardName = pxt.appTarget.appTheme.boardName || "???";
const boardDriveName = pxt.appTarget.appTheme.driveDisplayName || pxt.appTarget.compile.driveName || "???";
// https://msdn.microsoft.com/en-us/library/cc848897.aspx
// "For security reasons, data URIs are restricted to downloaded resources.
// Data URIs cannot be used for navigation, for scripting, or to populate frame or iframe elements"
const downloadAgain = !pxt.BrowserUtils.isIE() && !pxt.BrowserUtils.isEdge();
const docUrl = pxt.appTarget.appTheme.usbDocs;
const saveAs = pxt.BrowserUtils.hasSaveAs();
const htmlBody = `
<div class="ui three column grid stackable">
<div class="column">
<div class="ui">
<div class="image">
<img class="ui medium rounded image" src="./static/download/connect.svg" style="height:109px;width:261px;margin-bottom:1rem;">
</div>
<div class="content">
<div class="description">
<span class="ui yellow circular label">1</span>
<strong>${lf("Connect EV3 to computer with USB cable")}</strong>
<br/>
${lf("Use the miniUSB port on top of EV3 brick")}
</div>
</div>
</div>
</div>
<div class="column">
<div class="ui">
<div class="image">
<img class="ui medium rounded image" src="./static/download/firmware.svg" style="height:109px;width:261px;margin-bottom:1rem;">
</div>
<div class="content">
<div class="description">
<span class="ui blue circular label">2</span>
<strong>${lf("Make sure you have the latest EV3 firmware")}</strong>
<br/>
<a href="" target="_blank">${lf("Click here to update to latest firmware")}</a>
</div>
</div>
</div>
</div>
<div class="column">
<div class="ui">
<div class="image">
<img class="ui medium rounded image" src="./static/download/transfer.svg" style="height:109px;width:261px;margin-bottom:1rem;">
</div>
<div class="content">
<div class="description">
<span class="ui blue circular label">3</span>
${lf("Move the .uf2 file to EV3 brick")}
<br/>
${lf("Locate the downloaded .uf2 file and drag it to the EV3 drive")}
</div>
</div>
</div>
</div>
</div>`;
return confirmAsync({
header: lf("Download to your EV3"),
htmlBody,
hasCloseIcon: true,
hideCancel: true,
hideAgree: false,
agreeLbl: lf("I got it"),
buttons: [downloadAgain ? {
label: fn,
icon: "download",
class: "lightgrey focused",
url,
fileName: fn
} : undefined, docUrl ? {
label: lf("Help"),
icon: "help",
class: "lightgrey",
url: docUrl
} : undefined]
//timeout: 20000
}).then(() => { });
}
}; };
initAsync().catch(e => { initAsync().catch(e => {
// probably no HID - we'll try this again upon deployment // probably no HID - we'll try this again upon deployment

View File

@ -40,7 +40,8 @@ export class FieldSpeed extends Blockly.FieldSlider implements Blockly.FieldCust
var labelContainer = document.createElement('div'); var labelContainer = document.createElement('div');
this.speedSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg") as SVGGElement; this.speedSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg") as SVGGElement;
pxsim.svg.hydrate(this.speedSVG, { pxsim.svg.hydrate(this.speedSVG, {
viewBox: "0 0 200 100" viewBox: "0 0 200 100",
width: "170"
}); });
labelContainer.appendChild(this.speedSVG); labelContainer.appendChild(this.speedSVG);
@ -58,7 +59,7 @@ export class FieldSpeed extends Blockly.FieldSlider implements Blockly.FieldCust
this.reporter = pxsim.svg.child(this.speedSVG, "text", { this.reporter = pxsim.svg.child(this.speedSVG, "text", {
'x': 100, 'y': 80, 'x': 100, 'y': 80,
'text-anchor': 'middle', 'alignment-baseline': 'middle', 'text-anchor': 'middle', 'dominant-baseline': 'middle',
'style': 'font-size: 50px', 'style': 'font-size: 50px',
'class': 'sim-text inverted number' 'class': 'sim-text inverted number'
}) as SVGTextElement; }) as SVGTextElement;

View File

@ -56,7 +56,7 @@ export class FieldTurnRatio extends Blockly.FieldSlider implements Blockly.Field
}, marker); }, marker);
this.reporter_ = pxsim.svg.child(svg, "text", { this.reporter_ = pxsim.svg.child(svg, "text", {
'x': FieldTurnRatio.HALF, 'y': 96, 'x': FieldTurnRatio.HALF, 'y': 96,
'text-anchor': 'middle', 'alignment-baseline': 'middle', 'text-anchor': 'middle', 'dominant-baseline': 'middle',
'style': 'font-size: 50px', 'style': 'font-size: 50px',
'class': 'sim-text inverted number' 'class': 'sim-text inverted number'
}) as SVGTextElement; }) as SVGTextElement;

View File

@ -1,5 +1,5 @@
{ {
"automation": "Automation, process control and robotic controllers\n\nProcess control, automation, robotics AI", "automation": "Automation, process control and robotic controllers",
"automation.Behavior": "A behavior", "automation.Behavior": "A behavior",
"automation.Behavior.update": "Called on each behavior iteration even for suppresed behaviors", "automation.Behavior.update": "Called on each behavior iteration even for suppresed behaviors",
"automation.Behavior.update|param|elapsed": "milli seconds since last call", "automation.Behavior.update|param|elapsed": "milli seconds since last call",
@ -8,6 +8,7 @@
"automation.BehaviorManager.add|param|behavior": "the behavior to add", "automation.BehaviorManager.add|param|behavior": "the behavior to add",
"automation.BehaviorManager.start": "Starts the behavior control loop", "automation.BehaviorManager.start": "Starts the behavior control loop",
"automation.BehaviorManager.stop": "Stops the execution loop", "automation.BehaviorManager.stop": "Stops the execution loop",
"automation.PIDController": "A PID controller.\n* Reference: Feedback System, Karl Johan Astrom & Rickard M. Murry",
"automation.PIDController.compute": "Computes the output based on the system state", "automation.PIDController.compute": "Computes the output based on the system state",
"automation.PIDController.setControlSaturation": "Sets the control saturation values", "automation.PIDController.setControlSaturation": "Sets the control saturation values",
"automation.PIDController.setControlSaturation|param|high": "highest control value, eg: 100", "automation.PIDController.setControlSaturation|param|high": "highest control value, eg: 100",

View File

@ -1,5 +1,5 @@
{ {
"automation.PIDController.compute|block": "%pid|compute for timestep %timestep|(s) at state %y", "automation.PIDController.compute|block": "%pid|compute for timestep %timestep|(ms) at state %y",
"automation.PIDController.setControlSaturation|block": "set %pid|control saturation from %low|to %high", "automation.PIDController.setControlSaturation|block": "set %pid|control saturation from %low|to %high",
"automation.PIDController.setDerivativeFilter|block": "set %pid|derivative filter %N", "automation.PIDController.setDerivativeFilter|block": "set %pid|derivative filter %N",
"automation.PIDController.setGains|block": "set %pid|gains kp %kp|ki %ki|kd %kd", "automation.PIDController.setGains|block": "set %pid|gains kp %kp|ki %ki|kd %kd",

View File

@ -134,7 +134,7 @@
"control.panic": "Display an error code and stop the program.", "control.panic": "Display an error code and stop the program.",
"control.panic|param|code": "an error number to display. eg: 5", "control.panic|param|code": "an error number to display. eg: 5",
"control.reset": "Reset the device.", "control.reset": "Reset the device.",
"control.runInBackground": "Run other code in the background.", "control.runInParallel": "Run other code in the parallel.",
"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",

View File

@ -25,10 +25,11 @@
"control.onEvent|block": "on event|from %src|with value %value", "control.onEvent|block": "on event|from %src|with value %value",
"control.panic|block": "panic %code", "control.panic|block": "panic %code",
"control.reset|block": "reset", "control.reset|block": "reset",
"control.runInBackground|block": "run in background", "control.runInParallel|block": "run in parallel",
"control.waitForEvent|block": "wait for event|from %src|with value %value", "control.waitForEvent|block": "wait for event|from %src|with value %value",
"control.waitMicros|block": "wait (µs)%micros", "control.waitMicros|block": "wait (µs)%micros",
"control|block": "control", "control|block": "control",
"fieldeditors|block": "fieldeditors",
"loops.forever|block": "forever", "loops.forever|block": "forever",
"loops.pause|block": "pause %pause=timePicker|ms", "loops.pause|block": "pause %pause=timePicker|ms",
"loops|block": "loops", "loops|block": "loops",

View File

@ -17,7 +17,8 @@
"control.cpp", "control.cpp",
"control.ts", "control.ts",
"serial.cpp", "serial.cpp",
"serial.ts" "serial.ts",
"fieldeditors.ts"
], ],
"testFiles": [ "testFiles": [
"test.ts" "test.ts"

View File

@ -118,11 +118,11 @@ declare namespace control {
function waitMicros(micros: int32): void; function waitMicros(micros: int32): void;
/** /**
* Run other code in the background. * Run other code in the parallel.
*/ */
//% help=control/run-in-background blockAllowMultiple=1 afterOnStart=true //% help=control/run-in-parallel handlerStatement=1
//% blockId="control_run_in_background" block="run in background" blockGap=8 shim=control::runInBackground //% blockId="control_run_in_parallel" block="run in parallel" blockGap=8 shim=control::runInParallel
function runInBackground(a: () => void): void; function runInParallel(a: () => void): void;
/** /**
* Blocks the calling thread until the specified event is raised. * Blocks the calling thread until the specified event is raised.

View File

@ -1,3 +1,5 @@
<xml xmlns="http://www.w3.org/1999/xhtml"> <xml xmlns="http://www.w3.org/1999/xhtml">
<block type="forever"></block> <variables></variables>
<block type="pxt-on-start" x="0" y="0"></block>
<block type="forever" x="176" y="0"></block>
</xml> </xml>

View File

@ -1,11 +1,10 @@
{ {
"chassis": "A differential drive robot",
"chassis.Chassis": "A differential drive robot", "chassis.Chassis": "A differential drive robot",
"chassis.Chassis.drive": "Makes a differential drive robot move with a given speed (cm/s) and rotation rate (deg/s)\nusing a unicycle model.", "chassis.Chassis.drive": "Makes a differential drive robot move with a given speed (cm/s) and rotation rate (deg/s)\nusing a unicycle model.",
"chassis.Chassis.drive|param|rotationSpeed": "rotation of the robot around the center point, eg: 30", "chassis.Chassis.drive|param|rotationSpeed": "rotation of the robot around the center point, eg: 30",
"chassis.Chassis.drive|param|speed": "speed of the center point between motors, eg: 10", "chassis.Chassis.drive|param|speed": "speed of the center point between motors, eg: 10",
"chassis.Chassis.drive|param|value": "the amount of movement, eg: 2", "chassis.Chassis.setBaseLength": "Sets the base length in centimeters",
"chassis.Chassis.setMotors": "Sets the motors used by the chassis, default is B+C", "chassis.Chassis.setMotors": "Sets the motors used by the chassis, default is B+C",
"chassis.Chassis.setProperty": "Sets a property of the robot", "chassis.Chassis.setWheelRadius": "Sets the wheel radius in centimeters"
"chassis.Chassis.setProperty|param|property": "the property to set",
"chassis.Chassis.setProperty|param|value": "the value to set"
} }

View File

@ -1,9 +1,8 @@
{ {
"ChassisProperty.BaseLength|block": "base length (cm)",
"ChassisProperty.WheelRadius|block": "wheel radius (cm)",
"chassis.Chassis.drive|block": "drive %chassis|at %speed|cm/s|turning %rotationSpeed|deg/s", "chassis.Chassis.drive|block": "drive %chassis|at %speed|cm/s|turning %rotationSpeed|deg/s",
"chassis.Chassis.setBaseLength|block": "set %chassis|base length to %cm|(cm)",
"chassis.Chassis.setMotors|block": "set %chassis|motors to %motors", "chassis.Chassis.setMotors|block": "set %chassis|motors to %motors",
"chassis.Chassis.setProperty|block": "set %chassis|%property|to %value", "chassis.Chassis.setWheelRadius|block": "set %chassis|wheel radius to %cm|(cm)",
"chassis|block": "chassis", "chassis|block": "chassis",
"{id:category}Chassis": "Chassis" "{id:category}Chassis": "Chassis"
} }

View File

@ -1,10 +1,7 @@
enum ChassisProperty { /**
//% block="wheel radius (cm)" * A differential drive robot
WheelRadius, */
//% block="base length (cm)" //% weight=50 color=#cf00cf
BaseLength
}
namespace chassis { namespace chassis {
/** /**
* A differential drive robot * A differential drive robot
@ -29,13 +26,17 @@ namespace chassis {
* using a unicycle model. * using a unicycle model.
* @param speed speed of the center point between motors, eg: 10 * @param speed speed of the center point between motors, eg: 10
* @param rotationSpeed rotation of the robot around the center point, eg: 30 * @param rotationSpeed rotation of the robot around the center point, eg: 30
* @param value the amount of movement, eg: 2 * @param distance
* @param unit **/
*/
//% blockId=motorDrive block="drive %chassis|at %speed|cm/s|turning %rotationSpeed|deg/s" //% blockId=motorDrive block="drive %chassis|at %speed|cm/s|turning %rotationSpeed|deg/s"
//% inlineInputMode=inline //% inlineInputMode=inline
//% weight=95 blockGap=8 //% weight=95 blockGap=8
drive(speed: number, rotationSpeed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) { drive(speed: number, rotationSpeed: number, distance: number = 0) {
if (!speed) {
this.motors.stop();
return;
}
// speed is expressed in % // speed is expressed in %
const R = this.wheelRadius; // cm const R = this.wheelRadius; // cm
const L = this.baseLength; // cm const L = this.baseLength; // cm
@ -52,24 +53,28 @@ namespace chassis {
const sr = vr / maxw * 100; // % const sr = vr / maxw * 100; // %
const sl = vl / maxw * 100; // % const sl = vl / maxw * 100; // %
this.motors.tank(sr, sl, value, unit) // cm / (cm/s) = s
const seconds = distance / speed;
this.motors.tank(sr, sl, seconds, MoveUnit.Seconds)
} }
/** /**
* Sets a property of the robot * Sets the wheel radius in centimeters
* @param property the property to set * @param cm
* @param value the value to set
*/ */
//% blockId=chassisSetProperty block="set %chassis|%property|to %value" //% blockId=chassisSetWheelRadius block="set %chassis|wheel radius to %cm|(cm)"
//% blockGap=8 setWheelRadius(cm: number) {
//% weight=10 this.wheelRadius = cm;
setProperty(property: ChassisProperty, value: number) {
switch (property) {
case ChassisProperty.WheelRadius:
this.wheelRadius = Math.max(0.1, value); break;
case ChassisProperty.BaseLength:
this.baseLength = Math.max(0.1, value); break;
} }
/**
* Sets the base length in centimeters
* @param cm
*/
//% blockId=chassisSetBaseLength block="set %chassis|base length to %cm|(cm)"
setBaseLength(cm: number) {
this.baseLength = cm;
} }
/** /**
@ -81,6 +86,10 @@ namespace chassis {
setMotors(motors: motors.SynchedMotorPair) { setMotors(motors: motors.SynchedMotorPair) {
this.motors = motors; this.motors = motors;
} }
toString(): string {
return `chassis base ${this.baseLength}, wheel ${this.wheelRadius}`;
}
} }
//% fixedInstance whenUsed //% fixedInstance whenUsed

View File

@ -1,5 +1,6 @@
{ {
"sensors.ColorSensor": "The color sensor is a digital sensor that can detect the color or intensity\nof light that enters the small window on the face of the sensor.", "sensors.ColorSensor": "The color sensor is a digital sensor that can detect the color or intensity\nof light that enters the small window on the face of the sensor.",
"sensors.ColorSensor.calibrateLight": "Collects measurement of the light condition and adjusts the threshold to 10% / 90%.",
"sensors.ColorSensor.color": "Get the current color from the color sensor.", "sensors.ColorSensor.color": "Get the current color from the color sensor.",
"sensors.ColorSensor.colorMode": "Gets the current color mode", "sensors.ColorSensor.colorMode": "Gets the current color mode",
"sensors.ColorSensor.light": "Measures the ambient or reflected light value from 0 (darkest) to 100 (brightest).", "sensors.ColorSensor.light": "Measures the ambient or reflected light value from 0 (darkest) to 100 (brightest).",
@ -14,5 +15,8 @@
"sensors.ColorSensor.pauseForLight": "Waits for the given color to be detected", "sensors.ColorSensor.pauseForLight": "Waits for the given color to be detected",
"sensors.ColorSensor.setThreshold": "Sets a threshold value", "sensors.ColorSensor.setThreshold": "Sets a threshold value",
"sensors.ColorSensor.setThreshold|param|condition": "the dark or bright light condition", "sensors.ColorSensor.setThreshold|param|condition": "the dark or bright light condition",
"sensors.ColorSensor.setThreshold|param|value": "the value threshold" "sensors.ColorSensor.setThreshold|param|value": "the value threshold",
"sensors.ColorSensor.threshold": "Gets the threshold value",
"sensors.ColorSensor.threshold|param|condition": "the light condition",
"sensors.color": "Returns a color that the sensor can detect"
} }

View File

@ -13,6 +13,7 @@
"LightCondition.Dark|block": "dark", "LightCondition.Dark|block": "dark",
"LightIntensityMode.Ambient|block": "ambient light", "LightIntensityMode.Ambient|block": "ambient light",
"LightIntensityMode.Reflected|block": "reflected light", "LightIntensityMode.Reflected|block": "reflected light",
"sensors.ColorSensor.calibrateLight|block": "calibrate|%sensor|for %mode|light",
"sensors.ColorSensor.color|block": "%sensor| color", "sensors.ColorSensor.color|block": "%sensor| color",
"sensors.ColorSensor.light|block": "%sensor|%mode", "sensors.ColorSensor.light|block": "%sensor|%mode",
"sensors.ColorSensor.onColorDetected|block": "on %sensor|detected color %color", "sensors.ColorSensor.onColorDetected|block": "on %sensor|detected color %color",
@ -20,10 +21,12 @@
"sensors.ColorSensor.pauseForColor|block": "pause %sensor|for color %color", "sensors.ColorSensor.pauseForColor|block": "pause %sensor|for color %color",
"sensors.ColorSensor.pauseForLight|block": "pause %sensor|for %mode|%condition", "sensors.ColorSensor.pauseForLight|block": "pause %sensor|for %mode|%condition",
"sensors.ColorSensor.setThreshold|block": "set %sensor|%condition|to %value", "sensors.ColorSensor.setThreshold|block": "set %sensor|%condition|to %value",
"sensors.ColorSensor.threshold|block": "%sensor|%condition",
"sensors.color1|block": "color 1", "sensors.color1|block": "color 1",
"sensors.color2|block": "color 2", "sensors.color2|block": "color 2",
"sensors.color3|block": "color 3", "sensors.color3|block": "color 3",
"sensors.color4|block": "color 4", "sensors.color4|block": "color 4",
"sensors.color|block": "color %color",
"sensors|block": "sensors", "sensors|block": "sensors",
"{id:category}Sensors": "Sensors", "{id:category}Sensors": "Sensors",
"{id:group}Color Sensor": "Color Sensor", "{id:group}Color Sensor": "Color Sensor",

View File

@ -19,29 +19,29 @@ enum LightIntensityMode {
} }
const enum ColorSensorColor { const enum ColorSensorColor {
//% block="none" //% block="none" blockIdentity=sensors.color
None, None,
//% block="black" //% block="black" blockIdentity=sensors.color
Black, Black,
//% block="blue" //% block="blue" blockIdentity=sensors.color
Blue, Blue,
//% block="green" //% block="green" blockIdentity=sensors.color
Green, Green,
//% block="yellow" //% block="yellow" blockIdentity=sensors.color
Yellow, Yellow,
//% block="red" //% block="red" blockIdentity=sensors.color
Red, Red,
//% block="white" //% block="white" blockIdentity=sensors.color
White, White,
//% block="brown" //% block="brown" blockIdentity=sensors.color
Brown, Brown,
} }
enum LightCondition { enum LightCondition {
//% block="dark" //% block="dark"
Dark = sensors.internal.ThresholdState.Low, Dark = sensors.ThresholdState.Low,
//$ block="bright" //$ block="bright"
Bright = sensors.internal.ThresholdState.High Bright = sensors.ThresholdState.High
} }
namespace sensors { namespace sensors {
@ -52,12 +52,14 @@ namespace sensors {
*/ */
//% fixedInstances //% fixedInstances
export class ColorSensor extends internal.UartSensor { export class ColorSensor extends internal.UartSensor {
thresholdDetector: sensors.internal.ThresholdDetector; thresholdDetector: sensors.ThresholdDetector;
calibrating: boolean;
constructor(port: number) { constructor(port: number) {
super(port) super(port)
this._setMode(ColorSensorMode.None); this._setMode(ColorSensorMode.None);
this.thresholdDetector = new sensors.internal.ThresholdDetector(this.id()); this.thresholdDetector = new sensors.ThresholdDetector(this.id());
this.calibrating = false;
} }
_colorEventValue(value: number) { _colorEventValue(value: number) {
@ -95,6 +97,7 @@ namespace sensors {
} }
_update(prev: number, curr: number) { _update(prev: number, curr: number) {
if (this.calibrating) return; // simply ignore data updates while calibrating
if (this.mode == ColorSensorMode.Color) if (this.mode == ColorSensorMode.Color)
control.raiseEvent(this._id, this._colorEventValue(curr)); control.raiseEvent(this._id, this._colorEventValue(curr));
else else
@ -154,6 +157,7 @@ namespace sensors {
//% sensor.fieldEditor="ports" //% sensor.fieldEditor="ports"
//% weight=98 //% weight=98
//% group="Color Sensor" //% group="Color Sensor"
//% blockGap=8
color(): ColorSensorColor { color(): ColorSensorColor {
this.setMode(ColorSensorMode.Color) this.setMode(ColorSensorMode.Color)
return this.getNumber(NumberFormat.UInt8LE, 0) return this.getNumber(NumberFormat.UInt8LE, 0)
@ -230,18 +234,88 @@ namespace sensors {
//% blockId=colorSetThreshold block="set %sensor|%condition|to %value" //% blockId=colorSetThreshold block="set %sensor|%condition|to %value"
//% group="Threshold" blockGap=8 weight=90 //% group="Threshold" blockGap=8 weight=90
//% value.min=0 value.max=100 //% value.min=0 value.max=100
//% sensor.fieldEditor="ports"
setThreshold(condition: LightCondition, value: number) { setThreshold(condition: LightCondition, value: number) {
if (condition == LightCondition.Dark) if (condition == LightCondition.Dark)
this.thresholdDetector.setLowThreshold(value) this.thresholdDetector.setLowThreshold(value)
else else
this.thresholdDetector.setHighThreshold(value); this.thresholdDetector.setHighThreshold(value);
} }
/**
* Gets the threshold value
* @param condition the light condition
*/
//% blockId=colorGetThreshold block="%sensor|%condition"
//% group="Threshold" blockGap=8 weight=89
//% sensor.fieldEditor="ports"
threshold(condition: LightCondition): number {
return this.thresholdDetector.threshold(<ThresholdState><number>LightCondition.Dark);
} }
//% whenUsed block="color 3" weight=90 fixedInstance jres=icons.port3 /**
* Collects measurement of the light condition and adjusts the threshold to 10% / 90%.
*/
//% blockId=colorCalibrateLight block="calibrate|%sensor|for %mode|light"
//% group="Threshold" weight=91 blockGap=8
//% sensor.fieldEditor="ports"
calibrateLight(mode: LightIntensityMode, deviation: number = 8) {
this.calibrating = true; // prevent events
this.light(mode); // trigger a read
pauseUntil(() => this.isActive()); // ensure sensor is live
let vold = 0;
let vcount = 0;
let min = 200;
let max = -200;
let k = 0;
while (k++ < 1000 && vcount < 50) {
let v = this.light(mode);
min = Math.min(min, v);
max = Math.max(max, v);
// detect if nothing has changed and stop calibration
if (Math.abs(v - vold) <= 2)
vcount++;
else {
vold = v;
vcount = 1;
}
// wait a bit
loops.pause(50);
}
// apply tolerance
const minDist = 10;
min = Math.max(minDist / 2, Math.min(min + deviation / 2, max - deviation / 2 - minDist / 2));
max = Math.min(100 - minDist / 2, Math.max(min + minDist, max - deviation / 2));
// apply thresholds
this.thresholdDetector.setLowThreshold(min);
this.thresholdDetector.setHighThreshold(max);
this.calibrating = false;
}
}
/**
* Returns a color that the sensor can detect
*/
//% shim=TD_ID
//% blockId=colorSensorColor block="color %color"
//% group="Color Sensor"
//% weight=97
export function color(color: ColorSensorColor): ColorSensorColor {
return color;
}
//% whenUsed block="color 3" weight=95 fixedInstance jres=icons.port3
export const color3: ColorSensor = new ColorSensor(3) export const color3: ColorSensor = new ColorSensor(3)
//% whenUsed block="color 1" weight=95 fixedInstance jres=icons.port1 //% whenUsed block="color 1" weight=90 fixedInstance jres=icons.port1
export const color1: ColorSensor = new ColorSensor(1) export const color1: ColorSensor = new ColorSensor(1)
//% whenUsed block="color 2" weight=90 fixedInstance jres=icons.port2 //% whenUsed block="color 2" weight=90 fixedInstance jres=icons.port2

View File

@ -3,9 +3,9 @@
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
if (sensors.color1.ambientLight() > 20) { if (sensors.color1.ambientLight() > 20) {
brick.setStatusLight(LightsPattern.Green) brick.setLight(BrickLight.Green)
} else { } else {
brick.setStatusLight(LightsPattern.Orange) brick.setLight(BrickLight.Orange)
} }
}) })
``` ```

View File

@ -3,9 +3,9 @@
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
if (sensors.color1.color() == ColorSensorColor.Green) { if (sensors.color1.color() == ColorSensorColor.Green) {
brick.setStatusLight(LightsPattern.Green) brick.setLight(BrickLight.Green)
} else { } else {
brick.setStatusLight(LightsPattern.Orange) brick.setLight(BrickLight.Orange)
} }
}) })
``` ```

View File

@ -3,9 +3,9 @@
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
if (sensors.color1.reflectedLight() > 20) { if (sensors.color1.reflectedLight() > 20) {
brick.setStatusLight(LightsPattern.Green) brick.setLight(BrickLight.Green)
} else { } else {
brick.setStatusLight(LightsPattern.Orange) brick.setLight(BrickLight.Orange)
} }
}) })
``` ```

View File

@ -29,11 +29,11 @@
"brick.buttonLeft": "Left button on the EV3 Brick.", "brick.buttonLeft": "Left button on the EV3 Brick.",
"brick.buttonRight": "Right button on the EV3 Brick.", "brick.buttonRight": "Right button on the EV3 Brick.",
"brick.buttonUp": "Up button on the EV3 Brick.", "brick.buttonUp": "Up button on the EV3 Brick.",
"brick.clearScreen": "Clears the screen", "brick.clearScreen": "Clear the screen",
"brick.printPorts": "Prints the port states on the screen", "brick.printPorts": "Print the port states on the screen",
"brick.setLight": "Set lights.", "brick.setLight": "Set lights.",
"brick.setLight|param|pattern": "the lights pattern to use. eg: BrickLight.Orange", "brick.setLight|param|pattern": "the lights pattern to use. eg: BrickLight.Orange",
"brick.showImage": "Shows an image on screen", "brick.showImage": "Show an image on the screen",
"brick.showImage|param|image": "image to draw", "brick.showImage|param|image": "image to draw",
"brick.showNumber": "Shows a number on the screen", "brick.showNumber": "Shows a number on the screen",
"brick.showNumber|param|line": "the line number to print the text at, eg: 1", "brick.showNumber|param|line": "the line number to print the text at, eg: 1",

View File

@ -63,13 +63,13 @@
"control|block": "control", "control|block": "control",
"motors.Motor.angle|block": "%motor|angle", "motors.Motor.angle|block": "%motor|angle",
"motors.Motor.clearCounts|block": "%motor|clear counts", "motors.Motor.clearCounts|block": "%motor|clear counts",
"motors.Motor.setRegulated|block": "set %motor|regulated %value", "motors.Motor.setRegulated|block": "set %motor|regulated %value=toggleOnOff",
"motors.Motor.speed|block": "%motor|speed", "motors.Motor.speed|block": "%motor|speed",
"motors.Motor.tacho|block": "%motor|tacho", "motors.Motor.tacho|block": "%motor|tacho",
"motors.MotorBase.pauseUntilReady|block": "%motor|pause until ready", "motors.MotorBase.pauseUntilReady|block": "%motor|pause until ready",
"motors.MotorBase.reset|block": "%motors|reset", "motors.MotorBase.reset|block": "%motors|reset",
"motors.MotorBase.setBrake|block": "set %motor|brake %brake", "motors.MotorBase.setBrake|block": "set %motor|brake %brake=toggleOnOff",
"motors.MotorBase.setReversed|block": "set %motor|reversed %reversed", "motors.MotorBase.setReversed|block": "set %motor|reversed %reversed=toggleOnOff",
"motors.MotorBase.setSpeed|block": "set %motor|speed to %speed=motorSpeedPicker|%", "motors.MotorBase.setSpeed|block": "set %motor|speed to %speed=motorSpeedPicker|%",
"motors.MotorBase.stop|block": "%motors|stop", "motors.MotorBase.stop|block": "%motors|stop",
"motors.SynchedMotorPair.steer|block": "steer %chassis|turn ratio %turnRatio=motorTurnRatioPicker|speed %speed=motorSpeedPicker|%", "motors.SynchedMotorPair.steer|block": "steer %chassis|turn ratio %turnRatio=motorTurnRatioPicker|speed %speed=motorSpeedPicker|%",
@ -101,6 +101,7 @@
"{id:category}Motors": "Motors", "{id:category}Motors": "Motors",
"{id:category}Output": "Output", "{id:category}Output": "Output",
"{id:category}Screen": "Screen", "{id:category}Screen": "Screen",
"{id:category}Sensors": "Sensors",
"{id:category}Serial": "Serial", "{id:category}Serial": "Serial",
"{id:group}Buttons": "Buttons", "{id:group}Buttons": "Buttons",
"{id:group}Counters": "Counters", "{id:group}Counters": "Counters",

View File

@ -5,6 +5,7 @@ namespace brick {
*/ */
//% blockId=brickBatteryLevel block="battery level" //% blockId=brickBatteryLevel block="battery level"
//% group="More" //% group="More"
//% help=brick/battery-level
export function batteryLevel(): number { export function batteryLevel(): number {
const info = sensors.internal.getBatteryInfo(); const info = sensors.internal.getBatteryInfo();
return info.current; return info.current;

View File

@ -75,7 +75,7 @@ namespace brick {
* 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 //% help=brick/button/is-pressed
//% block="%button|is pressed" //% block="%button|is pressed"
//% blockId=buttonIsPressed //% blockId=buttonIsPressed
//% parts="brick" //% parts="brick"
@ -91,7 +91,7 @@ namespace brick {
* 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 //% help=brick/button/was-pressed
//% block="%button|was pressed" //% block="%button|was pressed"
//% blockId=buttonWasPressed //% blockId=buttonWasPressed
//% parts="brick" //% parts="brick"
@ -111,7 +111,7 @@ namespace brick {
* @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 //% help=brick/button/on-event
//% blockId=buttonEvent block="on %button|%event" //% blockId=buttonEvent block="on %button|%event"
//% parts="brick" //% parts="brick"
//% blockNamespace=brick //% blockNamespace=brick
@ -126,7 +126,7 @@ namespace brick {
* Waits until the event is raised * Waits until the event is raised
* @param ev the event to wait for * @param ev the event to wait for
*/ */
//% help=input/button/pause-until //% help=brick/button/pause-until
//% blockId=buttonWaitUntil block="pause until %button|%event" //% blockId=buttonWaitUntil block="pause until %button|%event"
//% parts="brick" //% parts="brick"
//% blockNamespace=brick //% blockNamespace=brick
@ -251,6 +251,7 @@ namespace brick {
*/ */
//% blockId=setLights block="set light to %pattern" //% blockId=setLights block="set light to %pattern"
//% weight=100 group="Buttons" //% weight=100 group="Buttons"
//% help=brick/set-light
export function setLight(pattern: BrickLight): void { export function setLight(pattern: BrickLight): void {
if (currPattern === pattern) if (currPattern === pattern)
return return

View File

@ -11,7 +11,7 @@ namespace sensors.internal {
// This is implementation for the simulator. // This is implementation for the simulator.
control.runInBackground(() => { control.runInParallel(() => {
let prev = query() let prev = query()
changeHandler(prev, prev) changeHandler(prev, prev)
while (true) { while (true) {
@ -196,83 +196,6 @@ namespace sensors.internal {
} }
} }
export enum ThresholdState {
Normal = 1,
High = 2,
Low = 3,
}
export class ThresholdDetector {
public id: number;
private min: number;
private max: number;
private lowThreshold: number;
private highThreshold: number;
private level: number;
public state: ThresholdState;
constructor(id: number, min = 0, max = 100, lowThreshold = 20, highThreshold = 80) {
this.id = id;
this.min = min;
this.max = max;
this.lowThreshold = lowThreshold;
this.highThreshold = highThreshold;
this.level = Math.ceil((max - min) / 2);
this.state = ThresholdState.Normal;
}
public setLevel(level: number) {
if (this == null) return
this.level = this.clampValue(level);
if (this.level >= this.highThreshold) {
this.setState(ThresholdState.High);
}
else if (this.level <= this.lowThreshold) {
this.setState(ThresholdState.Low);
}
else {
this.setState(ThresholdState.Normal);
}
}
public setLowThreshold(value: number) {
this.lowThreshold = this.clampValue(value);
this.highThreshold = Math.max(this.lowThreshold + 1, this.highThreshold);
}
public setHighThreshold(value: number) {
this.highThreshold = this.clampValue(value);
this.lowThreshold = Math.min(this.highThreshold - 1, this.lowThreshold);
}
private clampValue(value: number) {
if (value < this.min) {
return this.min;
}
else if (value > this.max) {
return this.max;
}
return value;
}
private setState(state: ThresholdState) {
if (this.state == state) return;
this.state = state;
switch (state) {
case ThresholdState.High:
control.raiseEvent(this.id, ThresholdState.High);
break;
case ThresholdState.Low:
control.raiseEvent(this.id, ThresholdState.Low);
break;
case ThresholdState.Normal:
break;
}
}
}
export class UartSensor extends Sensor { export class UartSensor extends Sensor {
protected mode: number // the mode user asked for protected mode: number // the mode user asked for
protected realmode: number // the mode the hardware is in protected realmode: number // the mode the hardware is in
@ -499,3 +422,91 @@ namespace sensors.internal {
TST_UART_WRITE = 0xc048740a, TST_UART_WRITE = 0xc048740a,
} }
} }
namespace sensors {
export enum ThresholdState {
Normal = 1,
High = 2,
Low = 3,
}
export class ThresholdDetector {
public id: number;
public min: number;
public max: number;
public lowThreshold: number;
public highThreshold: number;
public level: number;
public state: ThresholdState;
constructor(id: number, min = 0, max = 100, lowThreshold = 20, highThreshold = 80) {
this.id = id;
this.min = min;
this.max = max;
this.lowThreshold = lowThreshold;
this.highThreshold = highThreshold;
this.level = Math.ceil((max - min) / 2);
this.state = ThresholdState.Normal;
}
public setLevel(level: number) {
if (this == null) return
this.level = this.clampValue(level);
if (this.level >= this.highThreshold) {
this.setState(ThresholdState.High);
}
else if (this.level <= this.lowThreshold) {
this.setState(ThresholdState.Low);
}
else {
const interval = (this.highThreshold - this.lowThreshold) / 6;
if ((this.state == ThresholdState.High && this.level < this.highThreshold - interval) ||
(this.state == ThresholdState.Low && this.level > this.lowThreshold + interval))
this.setState(ThresholdState.Normal);
}
}
public threshold(t: ThresholdState): number {
switch(t) {
case ThresholdState.High: return this.highThreshold;
case ThresholdState.Low: return this.lowThreshold;
default: return (this.max - this.min) / 2;
}
}
public setLowThreshold(value: number) {
this.lowThreshold = this.clampValue(value);
this.highThreshold = Math.max(this.lowThreshold + 1, this.highThreshold);
}
public setHighThreshold(value: number) {
this.highThreshold = this.clampValue(value);
this.lowThreshold = Math.min(this.highThreshold - 1, this.lowThreshold);
}
private clampValue(value: number) {
if (value < this.min) {
return this.min;
}
else if (value > this.max) {
return this.max;
}
return value;
}
private setState(state: ThresholdState) {
if (this.state == state) return;
this.state = state;
switch (state) {
case ThresholdState.High:
control.raiseEvent(this.id, ThresholdState.High);
break;
case ThresholdState.Low:
control.raiseEvent(this.id, ThresholdState.Low);
break;
}
}
}
}

View File

@ -271,7 +271,12 @@ void setupThread(Action a, TValue arg = 0, void (*runner)(Thread *) = NULL, TVal
} }
} }
void runInBackground(Action a) { void releaseFiber() {
stopUser();
pthread_exit(NULL);
}
void runInParallel(Action a) {
setupThread(a); setupThread(a);
} }

View File

@ -161,8 +161,7 @@ namespace motors {
* Sets the automatic brake on or off when the motor is off * Sets the automatic brake on or off when the motor is off
* @param brake a value indicating if the motor should break when off * @param brake a value indicating if the motor should break when off
*/ */
//% blockId=outputMotorSetBrakeMode block="set %motor|brake %brake" //% blockId=outputMotorSetBrakeMode block="set %motor|brake %brake=toggleOnOff"
//% brake.fieldEditor=toggleonoff
//% weight=60 blockGap=8 //% weight=60 blockGap=8
//% group="Move" //% group="Move"
setBrake(brake: boolean) { setBrake(brake: boolean) {
@ -173,8 +172,7 @@ namespace motors {
/** /**
* Reverses the motor polarity * Reverses the motor polarity
*/ */
//% blockId=motorSetReversed block="set %motor|reversed %reversed" //% blockId=motorSetReversed block="set %motor|reversed %reversed=toggleOnOff"
//% reversed.fieldEditor=toggleonoff
//% weight=59 blockGap=8 //% weight=59 blockGap=8
//% group="Move" //% group="Move"
setReversed(reversed: boolean) { setReversed(reversed: boolean) {
@ -193,6 +191,14 @@ namespace motors {
stop() { stop() {
this.init(); this.init();
stop(this._port, this._brake); stop(this._port, this._brake);
this.settle();
}
private settle() {
// if we've recently completed a motor command with brake
// allow 500ms for robot to settle
if(this._brake)
loops.pause(500);
} }
/** /**
@ -253,6 +259,8 @@ namespace motors {
this._move(useSteps, stepsOrTime, speed); this._move(useSteps, stepsOrTime, speed);
// wait till motor is done with this work // wait till motor is done with this work
this.pauseUntilReady(); this.pauseUntilReady();
// allow robot to settle
this.settle();
} }
/** /**
@ -327,8 +335,7 @@ namespace motors {
* Indicates if the motor speed should be regulated. Default is true. * Indicates if the motor speed should be regulated. Default is true.
* @param value true for regulated motor * @param value true for regulated motor
*/ */
//% blockId=outputMotorSetRegulated block="set %motor|regulated %value" //% blockId=outputMotorSetRegulated block="set %motor|regulated %value=toggleOnOff"
//% value.fieldEditor=toggleonoff
//% weight=58 //% weight=58
//% group="Move" //% group="Move"
setRegulated(value: boolean) { setRegulated(value: boolean) {

View File

@ -72,6 +72,7 @@ namespace brick {
*/ */
//% blockId=screen_print block="show string %text|at line %line" //% blockId=screen_print block="show string %text|at line %line"
//% weight=98 group="Screen" inlineInputMode="inline" blockGap=8 //% weight=98 group="Screen" inlineInputMode="inline" blockGap=8
//% help=brick/show-string
//% line.min=1 line.max=10 //% line.min=1 line.max=10
export function showString(text: string, line: number) { export function showString(text: string, line: number) {
const NUM_LINES = 9; const NUM_LINES = 9;
@ -87,6 +88,7 @@ namespace brick {
*/ */
//% blockId=screenShowNumber block="show number %name|at line %line" //% blockId=screenShowNumber block="show number %name|at line %line"
//% weight=96 group="Screen" inlineInputMode="inline" blockGap=8 //% weight=96 group="Screen" inlineInputMode="inline" blockGap=8
//% help=brick/show-number
//% line.min=1 line.max=10 //% line.min=1 line.max=10
export function showNumber(value: number, line: number) { export function showNumber(value: number, line: number) {
showString("" + value, line); showString("" + value, line);
@ -99,6 +101,7 @@ namespace brick {
*/ */
//% blockId=screenShowValue block="show value %name|= %text|at line %line" //% blockId=screenShowValue block="show value %name|= %text|at line %line"
//% weight=96 group="Screen" inlineInputMode="inline" blockGap=8 //% weight=96 group="Screen" inlineInputMode="inline" blockGap=8
//% help=brick/show-value
//% line.min=1 line.max=10 //% line.min=1 line.max=10
export function showValue(name: string, value: number, line: number) { export function showValue(name: string, value: number, line: number) {
value = Math.round(value * 1000) / 1000; value = Math.round(value * 1000) / 1000;
@ -136,11 +139,12 @@ namespace brick {
} }
/** /**
* Shows an image on screen * Show an image on the screen
* @param image image to draw * @param image image to draw
*/ */
//% blockId=screen_show_image block="show image %image=screen_image_picker" //% blockId=screen_show_image block="show image %image=screen_image_picker"
//% weight=100 group="Screen" blockGap=8 //% weight=100 group="Screen" blockGap=8
//% help=brick/show-image
export function showImage(image: Image) { export function showImage(image: Image) {
if (!image) return; if (!image) return;
image.draw(0, 0, Draw.Normal); image.draw(0, 0, Draw.Normal);
@ -160,10 +164,11 @@ namespace brick {
} }
/** /**
* Clears the screen * Clear the screen
*/ */
//% blockId=screen_clear_screen block="clear screen" //% blockId=screen_clear_screen block="clear screen"
//% weight=90 group="Screen" //% weight=90 group="Screen"
//% help=brick/clear-screen
export function clearScreen() { export function clearScreen() {
screen.clear(); screen.clear();
} }
@ -208,9 +213,10 @@ namespace brick {
} }
/** /**
* Prints the port states on the screen * Print the port states on the screen
*/ */
//% blockId=brickPrintPorts block="print ports" //% blockId=brickPrintPorts block="print ports"
//% help=brick/print-ports
//% weight=1 group="Screen" //% weight=1 group="Screen"
export function printPorts() { export function printPorts() {
const col = 44; const col = 44;

View File

@ -1,3 +0,0 @@
# Datalog
A tiny libraty to create CSV datalog files.

View File

@ -1,11 +1,17 @@
{ {
"datalog": "A data logging framework",
"datalog.DatalogStorage": "A storage for datalog data",
"datalog.DatalogStorage.appendHeaders": "Appends the headers in datalog",
"datalog.DatalogStorage.appendRow": "Appends a row of data",
"datalog.DatalogStorage.flush": "Flushes any buffered data",
"datalog.DatalogStorage.init": "Initializes the storage",
"datalog.addRow": "Starts a row of data", "datalog.addRow": "Starts a row of data",
"datalog.addValue": "Adds a cell to the row of data", "datalog.addValue": "Adds a cell to the row of data",
"datalog.addValue|param|name": "name of the cell, eg: \"x\"", "datalog.addValue|param|name": "name of the cell, eg: \"x\"",
"datalog.addValue|param|value": "value of the cell, eg: 0", "datalog.addValue|param|value": "value of the cell, eg: 0",
"datalog.flush": "Commits any buffered row to disk", "datalog.flush": "Commits any buffered row to disk",
"datalog.setEnabled": "Turns on or off datalogging", "datalog.setEnabled": "Turns on or off datalogging",
"datalog.setFile": "Starts a new data logger for the given file", "datalog.setSampleInterval": "Sets the minimum number of milli seconds between rows",
"datalog.setFile|param|filename": "the filename, eg: \"datalog.csv\"", "datalog.setSampleInterval|param|millis": "milliseconds between each sample, eg: 50",
"datalog.setStorage": "* @param storage custom storage solution" "datalog.setStorage": "* @param storage custom storage solution"
} }

View File

@ -1,7 +1,8 @@
{ {
"datalog.addRow|block": "datalog add row", "datalog.addRow|block": "datalog add row",
"datalog.addValue|block": "datalog add %name|=%value", "datalog.addValue|block": "datalog add %name|=%value",
"datalog.setEnabled|block": "datalog %enabled", "datalog.setEnabled|block": "datalog %enabled=toggleOnOff",
"datalog.setSampleInterval|block": "set datalog sampling interval to %millis|(ms)",
"datalog|block": "datalog", "datalog|block": "datalog",
"{id:category}Datalog": "Datalog" "{id:category}Datalog": "Datalog"
} }

View File

@ -1,122 +0,0 @@
//% weight=100 color=#0fbc11 icon=""
namespace datalog {
let _headers: string[] = undefined;
let _headersLength: number;
let _values: number[];
let _buffer: string = "";
let _start: number;
let _filename = "datalog.csv";
let _storage: storage.Storage = storage.temporary;
let _enabled = true;
function clear() {
_headers = undefined;
_values = undefined;
_buffer = "";
}
function init() {
if (!_headers) {
_headers = [];
_headersLength = 0;
_start = control.millis();
_storage.remove(_filename);
}
_values = [];
}
function commit() {
// write row if any data
if (_values && _values.length > 0) {
// write headers for the first row
if (!_headersLength) {
_storage.appendCSVHeaders(_filename, _headers);
_headersLength = _storage.size(_filename);
}
// commit row data
_buffer += storage.toCSV(_values, _storage.csvSeparator);
// buffered writes
if (_buffer.length > 1024)
flush();
}
// clear values
_values = undefined;
}
/**
* Starts a row of data
*/
//% weight=100
//% blockId=datalogAddRow block="datalog add row"
export function addRow(): void {
if (!_enabled) return;
commit();
init();
const s = (control.millis() - _start) / 1000;
addValue("time (s)", s);
}
/**
* Adds a cell to the row of data
* @param name name of the cell, eg: "x"
* @param value value of the cell, eg: 0
*/
//% weight=99
//% blockId=datalogAddValue block="datalog add %name|=%value"
export function addValue(name: string, value: number) {
if (!_values) return;
let i = _headers.indexOf(name);
if (i < 0) {
_headers.push(name);
i = _headers.length - 1;
}
_values[i] = value;
}
/**
* Starts a new data logger for the given file
* @param filename the filename, eg: "datalog.csv"
*/
//%
export function setFile(filename: string) {
flush();
_filename = filename;
clear();
}
/**
*
* @param storage custom storage solution
*/
//%
export function setStorage(storage: storage.Storage) {
flush();
_storage = storage;
clear();
}
/**
* Commits any buffered row to disk
*/
//%
export function flush() {
if (_buffer) {
const b = _buffer;
_buffer = "";
_storage.append(_filename, b);
}
}
/**
* Turns on or off datalogging
* @param enabled
*/
//% blockId=datalogEnabled block="datalog %enabled"
//% enabled.fieldEditor=fieldonoff
export function setEnabled(enabled: boolean) {
flush();
_enabled = enabled;
}
}

View File

@ -1,14 +1,5 @@
{ {
"name": "datalog", "additionalFilePath": "../../node_modules/pxt-common-packages/libs/datalog",
"description": "Tiny data logging framework",
"files": [
"README.md",
"datalog.ts"
],
"testFiles": [
"test.ts"
],
"public": true,
"dependencies": { "dependencies": {
"core": "file:../core", "core": "file:../core",
"storage": "file:../storage" "storage": "file:../storage"

View File

@ -0,0 +1,57 @@
namespace datalog.ev3 {
/**
* A datalog storage for the EV3
*/
export class EV3DatalogStorage extends DatalogStorage {
private _filename: string;
private _buffer: string;
private _storage: storage.Storage;
/**
* Creates a new storage for the datalog
* @param storage
* @param filename
*/
constructor(storage: storage.Storage, filename: string) {
super();
this._filename = filename;
this._storage = storage;
}
/**
* Initializes the storage
*/
init(): void {
this._storage.remove(this._filename);
this._buffer = "";
}
/**
* Appends the headers in datalog
*/
appendHeaders(headers: string[]): void {
this._storage.appendCSVHeaders(this._filename, headers);
}
/**
* Appends a row of data
*/
appendRow(values: number[]): void {
// commit row data
this._buffer += storage.toCSV(values, this._storage.csvSeparator);
// buffered writes
if (this._buffer.length > 512)
this.flush();
}
/**
* Flushes any buffered data
*/
flush(): void {
if (this._buffer) {
const b = this._buffer;
this._buffer = "";
this._storage.append(this._filename, b);
}
}
}
// automatic hook up
datalog.setStorage(new datalog.ev3.EV3DatalogStorage(storage.temporary, "datalog.csv"));
}

View File

@ -1,6 +0,0 @@
loops.forever(function () {
datalog.addRow()
datalog.addValue("x", Math.random())
datalog.addValue("y", Math.random())
})

View File

@ -9,7 +9,6 @@ namespace brick {
//% color="#C8509B" weight=95 icon="\uf10f" //% color="#C8509B" weight=95 icon="\uf10f"
//% labelLineWidth=0 //% labelLineWidth=0
//% groups='["Touch Sensor", "Color Sensor", "Ultrasonic Sensor", "Gyro Sensor", "Infrared Sensor", "Remote Infrared Beacon", "Threshold"]' //% groups='["Touch Sensor", "Color Sensor", "Ultrasonic Sensor", "Gyro Sensor", "Infrared Sensor", "Remote Infrared Beacon", "Threshold"]'
//% groupIcons='["\uf101","\uf103","\uf102","","","\uf104"]'
namespace sensors { namespace sensors {
} }

View File

@ -7,6 +7,8 @@
"sensors.InfraredSensor.setThreshold": "Sets a threshold value", "sensors.InfraredSensor.setThreshold": "Sets a threshold value",
"sensors.InfraredSensor.setThreshold|param|condition": "the dark or bright light condition", "sensors.InfraredSensor.setThreshold|param|condition": "the dark or bright light condition",
"sensors.InfraredSensor.setThreshold|param|value": "the value threshold", "sensors.InfraredSensor.setThreshold|param|value": "the value threshold",
"sensors.InfraredSensor.threshold": "Gets the threshold value",
"sensors.InfraredSensor.threshold|param|condition": "the proximity condition",
"sensors.RemoteInfraredBeaconButton.isPressed": "Check if a remote button is currently pressed or not.", "sensors.RemoteInfraredBeaconButton.isPressed": "Check if a remote button is currently pressed or not.",
"sensors.RemoteInfraredBeaconButton.onEvent": "Do something when a button or sensor is clicked, up or down", "sensors.RemoteInfraredBeaconButton.onEvent": "Do something when a button or sensor is clicked, up or down",
"sensors.RemoteInfraredBeaconButton.onEvent|param|body": "code to run when the event is raised", "sensors.RemoteInfraredBeaconButton.onEvent|param|body": "code to run when the event is raised",

View File

@ -6,6 +6,7 @@
"sensors.InfraredSensor.proximity|block": "%sensor|proximity", "sensors.InfraredSensor.proximity|block": "%sensor|proximity",
"sensors.InfraredSensor.remoteCommand|block": "%sensor|remote command", "sensors.InfraredSensor.remoteCommand|block": "%sensor|remote command",
"sensors.InfraredSensor.setThreshold|block": "set %sensor|%condition|to %value", "sensors.InfraredSensor.setThreshold|block": "set %sensor|%condition|to %value",
"sensors.InfraredSensor.threshold|block": "%sensor|%condition",
"sensors.RemoteInfraredBeaconButton.isPressed|block": "%button|is pressed", "sensors.RemoteInfraredBeaconButton.isPressed|block": "%button|is pressed",
"sensors.RemoteInfraredBeaconButton.onEvent|block": "on %button|%event", "sensors.RemoteInfraredBeaconButton.onEvent|block": "on %button|%event",
"sensors.RemoteInfraredBeaconButton.wasPressed|block": "%button|was pressed", "sensors.RemoteInfraredBeaconButton.wasPressed|block": "%button|was pressed",

View File

@ -138,12 +138,12 @@ namespace sensors {
//% fixedInstances //% fixedInstances
export class InfraredSensor extends internal.UartSensor { export class InfraredSensor extends internal.UartSensor {
private channel: IrRemoteChannel; private channel: IrRemoteChannel;
private proximityThreshold: sensors.internal.ThresholdDetector; private proximityThreshold: sensors.ThresholdDetector;
constructor(port: number) { constructor(port: number) {
super(port) super(port)
this.channel = IrRemoteChannel.Ch0 this.channel = IrRemoteChannel.Ch0
this.proximityThreshold = new sensors.internal.ThresholdDetector(this._id, 0, 100, 10, 90); this.proximityThreshold = new sensors.ThresholdDetector(this._id, 0, 100, 10, 90);
irButton(0) // make sure buttons array is initalized irButton(0) // make sure buttons array is initalized
// and set the mode, as otherwise button events won't work // and set the mode, as otherwise button events won't work
@ -258,7 +258,7 @@ namespace sensors {
* @param value the value threshold * @param value the value threshold
*/ */
//% blockId=irSetThreshold block="set %sensor|%condition|to %value" //% blockId=irSetThreshold block="set %sensor|%condition|to %value"
//% group="Threshold" blockGap=8 //% group="Threshold" blockGap=8 weight=49
//% value.min=0 value.max=100 //% value.min=0 value.max=100
setThreshold(condition: InfraredSensorEvent, value: number) { setThreshold(condition: InfraredSensorEvent, value: number) {
if (condition == InfraredSensorEvent.ObjectNear) if (condition == InfraredSensorEvent.ObjectNear)
@ -266,6 +266,17 @@ namespace sensors {
else else
this.proximityThreshold.setHighThreshold(value); this.proximityThreshold.setHighThreshold(value);
} }
/**
* Gets the threshold value
* @param condition the proximity condition
*/
//% blockId=irGetThreshold block="%sensor|%condition"
//% group="Threshold" blockGap=8 weight=49
//% sensor.fieldEditor="ports"
threshold(condition: InfraredSensorEvent): number {
return this.proximityThreshold.threshold(<ThresholdState><number>LightCondition.Dark);
}
} }
//% fixedInstance whenUsed block="infrared 1" jres=icons.port1 //% fixedInstance whenUsed block="infrared 1" jres=icons.port1

View File

@ -1,7 +1,7 @@
{ {
"brick.Mood": "A mood", "brick.Mood": "A mood",
"brick.Mood.show": "Shows the mood on the EV3", "brick.Mood.show": "Shows the mood on the EV3",
"brick.showMood": "Shows a mood", "brick.showMood": "Show a mood on the brick's screen",
"moods.angry": "An angry mood", "moods.angry": "An angry mood",
"moods.awake": "A awake mood", "moods.awake": "A awake mood",
"moods.dizzy": "A dizzy mood", "moods.dizzy": "A dizzy mood",

View File

@ -0,0 +1,37 @@
# show Mood
Show a mood on the brick. A mood will have a image on the display along with a sound and solid or flashing light.
```sig
brick.showMood(moods.sleeping)
```
You can choose one of several moods to show on the display. Use a mood to help show what your @boardname@ is doing at the moment.
## Parameters
**mood**: A mood to show on the brick. Choose one of these moods:
>* ``sleeping``
* ``awake``
* ``tired``
* ``angry``
* ``sad``
* ``dizzy``
* ``knockedOut``
* ``middleLeft``
* ``middleRight``
* ``love``
* ``winking``
* ``neutral``
## Example
Show a ``winking`` mood on the brick.
```blocks
brick.showMood(moods.winking)
```
## See also
[show image](/reference/brick/show-image)

View File

@ -1,9 +1,10 @@
namespace brick { namespace brick {
/** /**
* Shows a mood * Show a mood on the brick's screen
*/ */
//% weight=90 //% weight=90
//% blockId=moodShow block="show mood %mood=mood_image_picker" //% blockId=moodShow block="show mood %mood=mood_image_picker"
//% help=brick/show-mood
//% weight=101 group="Screen" blockGap=8 //% weight=101 group="Screen" blockGap=8
export function showMood(mood: Mood) { export function showMood(mood: Mood) {
if(mood) if(mood)

View File

@ -291,6 +291,9 @@ namespace music {
export function playSoundEffect(sound: Sound) { export function playSoundEffect(sound: Sound) {
if (!sound || numSoundsPlaying >= soundsLimit) return; if (!sound || numSoundsPlaying >= soundsLimit) return;
numSoundsPlaying++; numSoundsPlaying++;
control.runInBackground(() => {sound.play(); numSoundsPlaying--;}); control.runInParallel(() => {
sound.play();
numSoundsPlaying--;
});
} }
} }

View File

@ -1,11 +1,11 @@
# Touch Sensor # Touch Sensor
```cards ```cards
sensors.touchSensor1.onEvent(TouchSensorEvent.Pressed, function () { sensors.touch1.onEvent(TouchSensorEvent.Pressed, function () {
brick.showImage(images.expressionsBigSmile) brick.showImage(images.expressionsBigSmile)
}) })
sensors.touchSensor1.isPressed(); sensors.touch1.isPressed();
sensors.touchSensor1.wasPressed(); sensors.touch1.wasPressed();
``` ```
## See Also ## See Also

View File

@ -2,10 +2,10 @@
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
if (sensors.touchSensor1.isPressed()) { if (sensors.touch1.isPressed()) {
brick.setStatusLight(LightsPattern.Green) brick.setLight(BrickLight.Green)
} else { } else {
brick.setStatusLight(LightsPattern.Orange) brick.setLight(BrickLight.Orange)
} }
}) })
``` ```

View File

@ -1,7 +1,7 @@
# On Event # On Event
```sig ```sig
sensors.touchSensor1.onEvent(TouchSensorEvent.Released, function () { }) sensors.touch1.onEvent(TouchSensorEvent.Released, function () { })
``` ```
# Parameters # Parameters
@ -10,7 +10,7 @@ sensors.touchSensor1.onEvent(TouchSensorEvent.Released, function () { })
```blocks ```blocks
sensors.touchSensor1.onEvent(TouchSensorEvent.Released, function () { sensors.touch1.onEvent(TouchSensorEvent.Released, function () {
brick.showImage(images.expressionsSick) brick.showImage(images.expressionsSick)
}) })
``` ```

View File

@ -2,10 +2,10 @@
```blocks ```blocks
loops.forever(function () { loops.forever(function () {
if (sensors.touchSensor1.wasPressed()) { if (sensors.touch1.wasPressed()) {
brick.setStatusLight(LightsPattern.Green) brick.setLight(BrickLight.Green)
} else { } else {
brick.setStatusLight(LightsPattern.Orange) brick.setLight(BrickLight.Orange)
} }
}) })
``` ```

View File

@ -5,5 +5,7 @@
"sensors.UltraSonicSensor.pauseUntil": "Waits for the event to occur", "sensors.UltraSonicSensor.pauseUntil": "Waits for the event to occur",
"sensors.UltraSonicSensor.setThreshold": "Sets a threshold value", "sensors.UltraSonicSensor.setThreshold": "Sets a threshold value",
"sensors.UltraSonicSensor.setThreshold|param|condition": "the dark or bright light condition", "sensors.UltraSonicSensor.setThreshold|param|condition": "the dark or bright light condition",
"sensors.UltraSonicSensor.setThreshold|param|value": "the value threshold" "sensors.UltraSonicSensor.setThreshold|param|value": "the value threshold",
"sensors.UltraSonicSensor.threshold": "Gets the threshold value",
"sensors.UltraSonicSensor.threshold|param|condition": "the proximity condition"
} }

View File

@ -6,6 +6,7 @@
"sensors.UltraSonicSensor.onEvent|block": "on %sensor|%event", "sensors.UltraSonicSensor.onEvent|block": "on %sensor|%event",
"sensors.UltraSonicSensor.pauseUntil|block": "pause until %sensor| %event", "sensors.UltraSonicSensor.pauseUntil|block": "pause until %sensor| %event",
"sensors.UltraSonicSensor.setThreshold|block": "set %sensor|%condition|to %value", "sensors.UltraSonicSensor.setThreshold|block": "set %sensor|%condition|to %value",
"sensors.UltraSonicSensor.threshold|block": "%sensor|%condition",
"sensors.ultrasonic1|block": "ultrasonic 1", "sensors.ultrasonic1|block": "ultrasonic 1",
"sensors.ultrasonic2|block": "ultrasonic 2", "sensors.ultrasonic2|block": "ultrasonic 2",
"sensors.ultrasonic3|block": "ultrasonic 3", "sensors.ultrasonic3|block": "ultrasonic 3",

View File

@ -2,21 +2,21 @@ enum UltrasonicSensorEvent {
//% block="object detected" //% block="object detected"
ObjectDetected = 10, ObjectDetected = 10,
//% block="object near" //% block="object near"
ObjectNear = sensors.internal.ThresholdState.Low, ObjectNear = sensors.ThresholdState.Low,
//% block="object far" //% block="object far"
ObjectFar = sensors.internal.ThresholdState.High ObjectFar = sensors.ThresholdState.High
} }
namespace sensors { namespace sensors {
//% fixedInstances //% fixedInstances
export class UltraSonicSensor extends internal.UartSensor { export class UltraSonicSensor extends internal.UartSensor {
private promixityThreshold: sensors.internal.ThresholdDetector; private promixityThreshold: sensors.ThresholdDetector;
private movementThreshold: number; private movementThreshold: number;
constructor(port: number) { constructor(port: number) {
super(port) super(port)
this.promixityThreshold = new sensors.internal.ThresholdDetector(this.id(), 0, 255, 10, 100); // range is 0..255cm this.promixityThreshold = new sensors.ThresholdDetector(this.id(), 0, 255, 10, 100); // range is 0..255cm
this.movementThreshold = 1; this.movementThreshold = 1;
} }
@ -93,15 +93,31 @@ namespace sensors {
* @param value the value threshold * @param value the value threshold
*/ */
//% blockId=ultrasonicSetThreshold block="set %sensor|%condition|to %value" //% blockId=ultrasonicSetThreshold block="set %sensor|%condition|to %value"
//% group="Threshold" blockGap=8 //% group="Threshold" blockGap=8 weight=80
//% value.min=0 value.max=255 //% value.min=0 value.max=255
setThreshold(condition: UltrasonicSensorEvent, value: number) { setThreshold(condition: UltrasonicSensorEvent, value: number) {
switch(condition) { switch (condition) {
case UltrasonicSensorEvent.ObjectNear: this.promixityThreshold.setLowThreshold(value); break; case UltrasonicSensorEvent.ObjectNear: this.promixityThreshold.setLowThreshold(value); break;
case UltrasonicSensorEvent.ObjectFar: this.promixityThreshold.setHighThreshold(value); break; case UltrasonicSensorEvent.ObjectFar: this.promixityThreshold.setHighThreshold(value); break;
case UltrasonicSensorEvent.ObjectDetected: this.movementThreshold = value; break; case UltrasonicSensorEvent.ObjectDetected: this.movementThreshold = value; break;
} }
} }
/**
* Gets the threshold value
* @param condition the proximity condition
*/
//% blockId=ultrasonicGetThreshold block="%sensor|%condition"
//% group="Threshold" blockGap=8 weight=79
//% sensor.fieldEditor="ports"
threshold(condition: UltrasonicSensorEvent): number {
switch (condition) {
case UltrasonicSensorEvent.ObjectNear: this.promixityThreshold.threshold(ThresholdState.Low); break;
case UltrasonicSensorEvent.ObjectFar: this.promixityThreshold.threshold(ThresholdState.Low); break;
case UltrasonicSensorEvent.ObjectDetected: this.movementThreshold; break;
}
return 0;
}
} }
//% fixedInstance whenUsed block="ultrasonic 4" jres=icons.port4 //% fixedInstance whenUsed block="ultrasonic 4" jres=icons.port4

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "pxt-ev3", "name": "pxt-ev3",
"version": "0.0.64", "version": "0.0.79",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "pxt-ev3", "name": "pxt-ev3",
"version": "0.0.70", "version": "0.0.79",
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode", "description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
"private": true, "private": true,
"keywords": [ "keywords": [
@ -44,8 +44,8 @@
"webfonts-generator": "^0.4.0" "webfonts-generator": "^0.4.0"
}, },
"dependencies": { "dependencies": {
"pxt-common-packages": "0.15.7", "pxt-common-packages": "0.17.13",
"pxt-core": "3.0.11" "pxt-core": "3.0.29"
}, },
"scripts": { "scripts": {
"test": "node node_modules/pxt-core/built/pxt.js travis" "test": "node node_modules/pxt-core/built/pxt.js travis"

View File

@ -16,25 +16,8 @@ namespace pxsim.SoundMethods {
return incr(buf) return incr(buf)
} }
export function uint8ArrayToString(input: Uint8Array) { export function play(buf: RefBuffer) {
let len = input.length; return pxsim.AudioContextManager.playBufferAsync(buf);
let res = ""
for (let i = 0; i < len; ++i)
res += String.fromCharCode(input[i]);
return res;
}
export function play(buf: RefBuffer, volume: number) {
if (!buf) {
return Promise.resolve();
}
return new Promise<void>(resolve => {
let url = "data:audio/wav;base64," + btoa(uint8ArrayToString(buf.data))
audio = new Audio(url)
audio.onended = () => resolve();
audio.onpause = () => resolve();
audio.play();
})
} }
export function stop() { export function stop() {

View File

@ -298,7 +298,14 @@ namespace pxsim.visuals {
this.layoutView.inject(this.element); this.layoutView.inject(this.element);
// Add EV3 module element // Add EV3 module element
this.layoutView.setBrick(new BrickView(-1)); const brickCloseIcon = this.getCloseIconView();
brickCloseIcon.registerClick(ev => {
this.layoutView.unselectBrick();
this.resize();
});
const brick =new BrickView(-1);
brick.setSelected(EV3View.isPreviousBrickSelected());
this.layoutView.setBrick(brick, brickCloseIcon);
this.resize(); this.resize();
@ -329,6 +336,12 @@ namespace pxsim.visuals {
this.screenCanvas = document.createElement("canvas"); this.screenCanvas = document.createElement("canvas");
this.screenCanvas.id = "board-screen-canvas"; this.screenCanvas.id = "board-screen-canvas";
this.screenCanvas.style.position = "absolute"; this.screenCanvas.style.position = "absolute";
this.screenCanvas.addEventListener(pxsim.pointerEvents.up, ev => {
this.layoutView.selectBrick();
this.resize();
})
this.screenCanvas.style.cursor = "pointer";
/*
this.screenCanvas.style.cursor = "crosshair"; this.screenCanvas.style.cursor = "crosshair";
this.screenCanvas.onmousemove = (e: MouseEvent) => { this.screenCanvas.onmousemove = (e: MouseEvent) => {
const x = e.clientX; const x = e.clientX;
@ -340,6 +353,7 @@ namespace pxsim.visuals {
this.screenCanvas.onmouseleave = () => { this.screenCanvas.onmouseleave = () => {
this.updateXY(SCREEN_WIDTH, SCREEN_HEIGHT); this.updateXY(SCREEN_WIDTH, SCREEN_HEIGHT);
} }
*/
this.screenCanvas.width = SCREEN_WIDTH; this.screenCanvas.width = SCREEN_WIDTH;
this.screenCanvas.height = SCREEN_HEIGHT; this.screenCanvas.height = SCREEN_HEIGHT;
@ -360,10 +374,12 @@ namespace pxsim.visuals {
// Save previous inputs for the next cycle // Save previous inputs for the next cycle
EV3View.previousSelectedInputs = ev3board().getInputNodes().map((node, index) => (this.getDisplayViewForNode(node.id, index).getSelected()) ? node.id : -1) EV3View.previousSelectedInputs = ev3board().getInputNodes().map((node, index) => (this.getDisplayViewForNode(node.id, index).getSelected()) ? node.id : -1)
EV3View.previousSeletedOutputs = ev3board().getMotors().map((node, index) => (this.getDisplayViewForNode(node.id, index).getSelected()) ? node.id : -1); EV3View.previousSeletedOutputs = ev3board().getMotors().map((node, index) => (this.getDisplayViewForNode(node.id, index).getSelected()) ? node.id : -1);
EV3View.previousSelectedBrick = this.layoutView.getBrick().getSelected();
} }
private static previousSelectedInputs: number[]; private static previousSelectedInputs: number[];
private static previousSeletedOutputs: number[]; private static previousSeletedOutputs: number[];
private static previousSelectedBrick: boolean;
private static isPreviousInputSelected(index: number, id: number) { private static isPreviousInputSelected(index: number, id: number) {
if (EV3View.previousSelectedInputs && EV3View.previousSelectedInputs[index] == id) { if (EV3View.previousSelectedInputs && EV3View.previousSelectedInputs[index] == id) {
@ -381,6 +397,12 @@ namespace pxsim.visuals {
return false; return false;
} }
private static isPreviousBrickSelected() {
const b = EV3View.previousSelectedBrick;
EV3View.previousSelectedBrick = false;
return !!b;
}
private begin() { private begin() {
this.running = true; this.running = true;
this.updateState(); this.updateState();

View File

@ -23,7 +23,7 @@ namespace pxsim.visuals {
this.reporter = pxsim.svg.child(this.group, "text", { this.reporter = pxsim.svg.child(this.group, "text", {
'x': this.getWidth() / 2, 'y': this.getHeight() / 2, 'x': this.getWidth() / 2, 'y': this.getHeight() / 2,
'text-anchor': 'middle', 'alignment-baseline': 'middle', 'text-anchor': 'middle', 'dominant-baseline': 'middle',
'style': 'font-size: 50px', 'style': 'font-size: 50px',
'class': 'sim-text inverted number' }) as SVGTextElement; 'class': 'sim-text inverted number' }) as SVGTextElement;

View File

@ -27,7 +27,7 @@ namespace pxsim.visuals {
this.reporter = pxsim.svg.child(this.group, "text", { this.reporter = pxsim.svg.child(this.group, "text", {
'x': this.getInnerWidth() / 2, 'y': this.getInnerHeight() / 2, 'x': this.getInnerWidth() / 2, 'y': this.getInnerHeight() / 2,
'text-anchor': 'middle', 'alignment-baseline': 'middle', 'text-anchor': 'middle', 'dominant-baseline': 'middle',
'style': 'font-size: 50px', 'style': 'font-size: 50px',
'class': 'sim-text inverted number' 'class': 'sim-text inverted number'
}) as SVGTextElement; }) as SVGTextElement;

View File

@ -37,6 +37,8 @@ namespace pxsim.visuals {
private outputWires: WireView[] = []; private outputWires: WireView[] = [];
private brick: BrickView; private brick: BrickView;
private brickCloseIcon: View = undefined;
private offsets: number[]; private offsets: number[];
private contentGroup: SVGGElement; private contentGroup: SVGGElement;
private scrollGroup: SVGGElement; private scrollGroup: SVGGElement;
@ -67,9 +69,13 @@ namespace pxsim.visuals {
this.position(); this.position();
} }
public setBrick(brick: BrickView) { public setBrick(brick: BrickView, brickCloseIcon: View) {
this.brick = brick; this.brick = brick;
this.brick.inject(this.scrollGroup); this.brick.inject(this.scrollGroup);
this.brickCloseIcon = brickCloseIcon;
this.addView(this.brickCloseIcon);
this.brickCloseIcon.setVisible(this.brick.getSelected());
this.position(); this.position();
} }
@ -77,6 +83,18 @@ namespace pxsim.visuals {
return this.brick; return this.brick;
} }
public unselectBrick() {
this.brick.setSelected(false);
this.brickCloseIcon.setVisible(false);
this.position();
}
public selectBrick() {
this.brick.setSelected(true);
this.brickCloseIcon.setVisible(true);
this.position();
}
public setInput(port: number, view: LayoutElement, control?: View, closeIcon?: View) { public setInput(port: number, view: LayoutElement, control?: View, closeIcon?: View) {
if (this.inputs[port] != view || this.inputControls[port] != control) { if (this.inputs[port] != view || this.inputControls[port] != control) {
if (this.inputs[port]) { if (this.inputs[port]) {
@ -224,17 +242,23 @@ namespace pxsim.visuals {
const noConnections = this.outputs.concat(this.inputs).filter(m => m.getId() != NodeType.Port).length == 0; const noConnections = this.outputs.concat(this.inputs).filter(m => m.getId() != NodeType.Port).length == 0;
if (noConnections) { // render the full brick layout, even when there are not connection
// No connections render the entire board // otherwise, it creates flickering of the simulator.
this.brick.resize(contentWidth, contentHeight); if (this.brick.getSelected()) {
this.brick.translate(0, 0); // render output button
const closeIconWidth = this.brickCloseIcon.getWidth();
const closeIconHeight = this.brickCloseIcon.getHeight();
this.brickCloseIcon.translate(contentWidth / 2 - closeIconWidth / 2, 0);
// render the entire board
this.brick.resize(contentWidth, contentHeight - closeIconHeight * 2);
this.brick.translate(0, closeIconHeight * 2);
// Hide all other connections // Hide all other connections
this.outputs.concat(this.inputs).forEach(m => m.setVisible(false)); this.outputs.concat(this.inputs).forEach(m => m.setVisible(false));
return; return;
} else {
this.outputs.concat(this.inputs).forEach(m => m.setVisible(true));
} }
this.outputs.concat(this.inputs).forEach(m => m.setVisible(true));
const moduleHeight = this.getModuleHeight(); const moduleHeight = this.getModuleHeight();

View File

@ -206,9 +206,11 @@ namespace pxsim.visuals {
} }
public setSelected(selected: boolean) { public setSelected(selected: boolean) {
if (this.selected != selected) {
this.selected = selected; this.selected = selected;
this.setChangedState(); this.setChangedState();
} }
}
protected setChangedState() { protected setChangedState() {
this.changed = true; this.changed = true;

View File

@ -2,10 +2,10 @@
User Global Variables User Global Variables
*******************************/ *******************************/
@importGoogleFonts: false; @importGoogleFonts: true;
@headerFont : Roboto,"Arial Narrow","Helvetica Neue",Helvetica,Arial,sans-serif; @headerFont : "Open Sans","Arial Narrow","Helvetica Neue",Helvetica,Arial,sans-serif;
@pageFont : Roboto,"Helvetica Neue",Helvetica,Arial,sans-serif; @pageFont : "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
@emSize : 14px; @emSize : 14px;
@fontSize : 13px; @fontSize : 13px;

View File

@ -112,3 +112,18 @@
color: @black !important; color: @black !important;
} }
} }
/** high contrast **/
.hc {
.ui.menu, #downloadArea,
.menubar .ui.menu.fixed .ui.item.editor-menuitem .item.active {
background-color: black !important;
color: white !important;
}
.ui.red.corner.label {
border-color: #d4000d!important;
}
.menubar .ui.menu.fixed .item.editor-menuitem .ui.grid {
border-color: white !important;
}
}