Compare commits
35 Commits
v1.4.19
...
users/GitH
Author | SHA1 | Date | |
---|---|---|---|
|
82671e5c27 | ||
|
b4a18f260d | ||
|
6b3f2da72c | ||
|
b9b21328b1 | ||
|
bef4ebac43 | ||
|
617fdeb747 | ||
|
c1aead1aa9 | ||
|
bd0cf05693 | ||
|
faae7133f5 | ||
|
5289850351 | ||
|
ba6e2f7174 | ||
|
7c5dfc474f | ||
|
5ab3a6ae96 | ||
|
ed2e1f23e9 | ||
|
a157943bf7 | ||
|
40aaf0fb18 | ||
|
b26cf289c3 | ||
|
f0821f8d6c | ||
|
1db61720fc | ||
|
ec2e561427 | ||
|
36d99c8a55 | ||
|
d003ef3f92 | ||
|
0723d4d7aa | ||
|
e65b16474e | ||
|
e8468ab62c | ||
|
8280937d92 | ||
|
180eb0f74e | ||
|
c16c4923af | ||
|
a792da8058 | ||
|
36b5d85dae | ||
|
3dc9b23802 | ||
|
d767a21f2f | ||
|
b3d504b1dc | ||
|
7f65f705c8 | ||
|
462aac0b65 |
@@ -1,5 +1,9 @@
|
||||
name: Compress images
|
||||
on: pull_request
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'docs/**.jpg'
|
||||
- 'docs/**.png'
|
||||
jobs:
|
||||
build:
|
||||
name: calibreapp/image-actions
|
||||
@@ -7,6 +11,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: calibreapp/image-actions
|
||||
uses: calibreapp/image-actions@master
|
||||
uses: docker://calibreapp/github-image-actions
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
40
.github/workflows/pxt-buildmain.yml
vendored
Normal file
40
.github/workflows/pxt-buildmain.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
name: pxt-buildmain
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'main'
|
||||
create:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: npm install
|
||||
run: |
|
||||
sudo apt-get install xvfb
|
||||
sudo npm install -g pxt
|
||||
npm install
|
||||
- name: pxt ci
|
||||
run: |
|
||||
pxt ci
|
||||
env:
|
||||
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
|
||||
PXT_ACCESS_TOKEN: ${{ secrets.PXT_ACCESS_TOKEN }}
|
||||
PXT_RELEASE_REPO: ${{ secrets.PXT_RELEASE_REPO }}
|
||||
NPM_ACCESS_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
|
||||
CHROME_BIN: chromium-browser
|
||||
DISPLAY: :99.0
|
||||
CI: true
|
31
.github/workflows/pxt-buildpr.yml
vendored
Normal file
31
.github/workflows/pxt-buildpr.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
name: pxt-buildpr
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: npm install
|
||||
run: |
|
||||
sudo apt-get install xvfb
|
||||
sudo npm install -g pxt
|
||||
npm install
|
||||
- name: pxt ci
|
||||
run: |
|
||||
pxt ci
|
||||
env:
|
||||
CHROME_BIN: chromium-browser
|
||||
DISPLAY: :99.0
|
||||
CI: true
|
39
.github/workflows/pxt-buildpush.yml
vendored
Normal file
39
.github/workflows/pxt-buildpush.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: pxt-buildpush
|
||||
|
||||
on:
|
||||
push:
|
||||
# main/master has its own build that includes the crowdin key
|
||||
branches-ignore:
|
||||
- 'main'
|
||||
- 'master'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: npm install
|
||||
run: |
|
||||
sudo apt-get install xvfb
|
||||
sudo npm install -g pxt
|
||||
npm install
|
||||
- name: pxt ci
|
||||
run: |
|
||||
pxt ci
|
||||
env:
|
||||
PXT_ACCESS_TOKEN: ${{ secrets.PXT_ACCESS_TOKEN }}
|
||||
PXT_RELEASE_REPO: ${{ secrets.PXT_RELEASE_REPO }}
|
||||
NPM_ACCESS_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
|
||||
CHROME_BIN: chromium-browser
|
||||
DISPLAY: :99.0
|
||||
CI: true
|
@@ -1,9 +0,0 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "8.9.0"
|
||||
script:
|
||||
- "node node_modules/pxt-core/built/pxt.js travis"
|
||||
sudo: false
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
41
SECURITY.md
Normal file
41
SECURITY.md
Normal file
@@ -0,0 +1,41 @@
|
||||
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK -->
|
||||
|
||||
## Security
|
||||
|
||||
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
||||
|
||||
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
|
||||
|
||||
## Reporting Security Issues
|
||||
|
||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||
|
||||
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
|
||||
|
||||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
|
||||
|
||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
|
||||
|
||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||
|
||||
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||
* Full paths of source file(s) related to the manifestation of the issue
|
||||
* The location of the affected source code (tag/branch/commit or direct URL)
|
||||
* Any special configuration required to reproduce the issue
|
||||
* Step-by-step instructions to reproduce the issue
|
||||
* Proof-of-concept or exploit code (if possible)
|
||||
* Impact of the issue, including how an attacker might exploit the issue
|
||||
|
||||
This information will help us triage your report more quickly.
|
||||
|
||||
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
|
||||
|
||||
## Preferred Languages
|
||||
|
||||
We prefer all communications to be in English.
|
||||
|
||||
## Policy
|
||||
|
||||
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
|
||||
|
||||
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"appref": "v"
|
||||
"appref": "v1.4.24"
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@ https://youtu.be/VIq8-6Egtqs
|
||||
## Supported browsers
|
||||
|
||||
* Chrome desktop, version 77 and higher, Windows 10 or Mac OS.
|
||||
* [Edge Insider desktop](https://www.microsoftedgeinsider.com), version 77 and higher, Windows 10 or Mac OS.
|
||||
* [Microsoft Edge Insider desktop](https://www.microsoftedgeinsider.com), version 77 and higher, Windows 10 or Mac OS.
|
||||
|
||||
To make sure your browser is up to date, go to the '...' menu, click "Help" then "About".
|
||||
|
||||
|
@@ -27,7 +27,6 @@ while (true) {
|
||||
music.playSoundEffectUntilDone(sounds.mechanicalMotorStart)
|
||||
music.playSoundEffectUntilDone(sounds.mechanicalMotorIdle);
|
||||
}
|
||||
pause(1);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -43,6 +42,5 @@ while (true) {
|
||||
music.playSoundEffectUntilDone(sounds.mechanicalMotorStart)
|
||||
music.playSoundEffectUntilDone(sounds.mechanicalMotorIdle);
|
||||
}
|
||||
pause(1);
|
||||
}
|
||||
```
|
@@ -213,7 +213,6 @@ Here are some fun programs for your @boardname@!
|
||||
"url":"/examples/happy-unhappy",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
{
|
||||
"name": "Turtle",
|
||||
"description": "Encode moves and run them on a driving base",
|
||||
"url":"/examples/turtle",
|
||||
|
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"appref": "v1.2.26"
|
||||
"appref": "v1.2.31"
|
||||
}
|
||||
|
@@ -2,16 +2,16 @@
|
||||
|
||||
## Example #example
|
||||
|
||||
Use the a wait and the timer to generate a crazy number.
|
||||
Use a wait and the timer to generate a number.
|
||||
|
||||
```blocks
|
||||
let crazy = 0
|
||||
let something = 0
|
||||
for (let i = 0; i < 100; i++) {
|
||||
control.waitMicros(100)
|
||||
crazy = control.millis()
|
||||
crazy += control.deviceSerialNumber()
|
||||
if (crazy != 0) {
|
||||
crazy = crazy / 1000000
|
||||
something = control.millis()
|
||||
something += control.deviceSerialNumber()
|
||||
if (something != 0) {
|
||||
something = something / 1000000
|
||||
}
|
||||
}
|
||||
```
|
BIN
docs/static/fll/context-help copy.jpg
vendored
Normal file
BIN
docs/static/fll/context-help copy.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
1
docs/static/icons/blocks.svg
vendored
Normal file
1
docs/static/icons/blocks.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="0 0 1000 1000"><path class="st1" d="m219.11872 941.69081 577.03056 0c22.8432 0 41.38224-18.53952 41.38224-41.49264l0-204.70272c-7.39392-24.82944-28.58112-27.14688-48.44448-8.27664-1.7664 0-21.62928 24.38784-67.31472 24.38784-54.51408-1.656-98.98608-41.93376-107.26224-94.57152l-0.552 0c-0.432-3.864-0.432-25.16016 0-29.02272l0.552 0c8.27616-52.52736 52.74816-92.91648 107.26224-94.57152 45.68544 0 65.4384 24.38784 67.31472 24.38784 19.31136 18.31824 40.71984 13.90416 48.44448-8.05584l0.096-189.36382c0-19.20145-13.24224-36.30625-31.00896-40.94065-3.312 0.8832-179.76336 0-179.76336 0-43.47888 3.5328-58.70736-25.71216-34.54032-51.20352 0-1.76639 24.38784-21.62879 24.38784-67.31472-1.656-54.51361-42.04416-98.98561-94.57152-107.26225l0-0.552c-3.864-0.432-25.16064-0.432-29.02272 0l0 0.552c-52.52736 8.27664-92.91648 52.74864-94.68192 107.26225 0 45.68593 24.38784 65.43888 24.38784 67.31472 24.27744 25.49136 14.12496 53.52096-34.31952 51.20352 0 0-176.4528 0.8832-179.76336 0-17.87712 4.63681-31.11936 21.6288-31.11936 40.94065l0 579.7891c0 22.84272 18.53904 41.49264 41.49216 41.49264z"/></svg>
|
After Width: | Height: | Size: 1.1 KiB |
27
docs/static/icons/js.svg
vendored
Normal file
27
docs/static/icons/js.svg
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 630 630">
|
||||
<!--
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011 Christopher Williams <chris@iterativedesigns.com>,
|
||||
Manuel Strehl <boldewyn@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
<path d="M 0 0 L 0 630 L 630 630 L 630 0 L 0 0 z M 479.45312 285.8457 C 517.09063 285.8457 544.15617 298.95789 563.60742 333.21289 L 517.51172 362.81445 C 507.36172 344.63195 496.36813 337.44336 479.45312 337.44336 C 462.11437 337.44336 451.11914 348.4382 451.11914 362.81445 C 451.11914 380.57695 462.11508 387.76547 487.48633 398.76172 L 502.28711 405.10547 C 552.61211 426.67422 580.94531 448.66242 580.94531 498.13867 C 580.94531 551.42617 539.07969 580.60352 482.83594 580.60352 C 427.85969 580.60352 392.33625 554.38711 375 520.13086 L 423.20703 492.21875 C 435.89703 512.9425 452.38961 528.16602 481.56836 528.16602 C 506.09961 528.16602 521.74219 515.90087 521.74219 498.98438 C 521.74219 478.68563 505.67172 471.4957 478.60547 459.6582 L 463.80859 453.31055 C 421.09359 435.1293 392.75781 412.29398 392.75781 364.08398 C 392.75781 319.68023 426.58938 285.8457 479.45312 285.8457 z M 283.63867 289.23047 L 342.8418 289.23047 L 342.8418 491.36719 C 342.8418 552.68719 306.89828 580.59961 254.45703 580.59961 C 207.09789 580.59961 179.60793 556.07214 165.65234 526.47266 L 165.65039 526.47461 L 165.65039 526.46875 C 165.65101 526.47007 165.65172 526.47134 165.65234 526.47266 L 213.86328 497.29688 C 223.16453 513.78813 231.62492 527.74023 251.91992 527.74023 C 271.37367 527.74023 283.63867 520.12955 283.63867 490.5293 L 283.63867 289.23047 z "/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
1
docs/static/icons/py.svg
vendored
Normal file
1
docs/static/icons/py.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="0 0 1000 1000" style="clip-rule:evenodd;fill-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;version:1.1"><path d="M503.415 730.842l-1.25 28.765 228.868 2.501c0 0 0.553 83.963 0 96.3 -3.535 78.874-47.389 95.999-128.817 110.057 -81.427 14.057-171.498 5.077-205.105 0 -108.896-16.451-121.313-112.558-121.313-112.558 0 0-0.481-204.44 0-240.124 0.481-35.684 45.171-100.562 101.302-102.553 71.167-2.524 194.071 2.041 252.63 0 58.56-2.04 130.375-58.917 132.569-132.568 2.193-73.652 1.25-115.06 1.25-115.06l90.047 2.502c0 0 119.183-4.794 121.312 246.377 1.989 234.636-179.876 216.383-180.093 216.361l-291.4 0Zm129.442 173.84c-23.814 0-43.147-19.334-43.147-43.147 0-23.814 19.333-43.148 43.147-43.148 23.814 0 43.147 19.334 43.147 43.148 0 23.813-19.333 43.147-43.147 43.147Zm-424.791-641.549l291.4 0 1.25-28.765 -228.868-2.501c0 0-0.552-83.963 0-96.3 3.535-78.874 47.389-95.999 128.817-110.057 81.427-14.057 171.499-5.077 205.106 0 108.895 16.451 121.312 112.558 121.312 112.558 0 0 0.481 204.44 0 240.124 -0.481 35.684-45.171 100.562-101.302 102.553 -71.167 2.524-194.071-2.041-252.63 0 -58.56 2.04-130.375 58.917-132.569 132.568 -2.193 73.651-1.25 115.059-1.25 115.059l-90.047-2.501c0 0-119.183 4.794-121.312-246.377 -1.99-234.776 180.093-216.361 180.093-216.361Zm161.958-173.84c23.814 0 43.147 19.334 43.147 43.147 0 23.814-19.333 43.148-43.147 43.148 -23.814 0-43.147-19.334-43.147-43.148 0-23.813 19.333-43.147 43.147-43.147Z"/></svg>
|
After Width: | Height: | Size: 1.5 KiB |
@@ -18,7 +18,7 @@
|
||||
}, {
|
||||
"name": "Stop At Object",
|
||||
"description": "Waits for the sensor to be pressed before continuing the program",
|
||||
"cardType": "tutorial",
|
||||
"cardType": "example",
|
||||
"url":"/tutorials/stop-at-object",
|
||||
"imageUrl":"/static/tutorials/pause-until-pressed.png"
|
||||
}]
|
||||
|
@@ -49,7 +49,7 @@ declare interface Serial extends EventTarget {
|
||||
requestPort(options: SerialPortRequestOptions): Promise<SerialPort>;
|
||||
}
|
||||
|
||||
class WebSerialPackageIO implements pxt.HF2.PacketIO {
|
||||
class WebSerialPackageIO implements pxt.packetio.PacketIO {
|
||||
onData: (v: Uint8Array) => void;
|
||||
onError: (e: Error) => void;
|
||||
onEvent: (v: Uint8Array) => void;
|
||||
@@ -59,6 +59,7 @@ class WebSerialPackageIO implements pxt.HF2.PacketIO {
|
||||
private _writer: any;
|
||||
|
||||
constructor(private port: SerialPort, private options: SerialOptions) {
|
||||
console.log(`serial: new io`)
|
||||
}
|
||||
|
||||
async readSerialAsync() {
|
||||
@@ -85,17 +86,24 @@ class WebSerialPackageIO implements pxt.HF2.PacketIO {
|
||||
return !!(<any>navigator).serial;
|
||||
}
|
||||
|
||||
static async mkPacketIOAsync(): Promise<pxt.HF2.PacketIO> {
|
||||
static portIos: WebSerialPackageIO[] = [];
|
||||
static async mkPacketIOAsync(): Promise<pxt.packetio.PacketIO> {
|
||||
const serial = (<any>navigator).serial;
|
||||
if (serial) {
|
||||
try {
|
||||
const requestOptions: SerialPortRequestOptions = {};
|
||||
const port = await serial.requestPort(requestOptions);
|
||||
const options: SerialOptions = {
|
||||
baudrate: 460800,
|
||||
buffersize: 4096
|
||||
};
|
||||
return new WebSerialPackageIO(port, options);
|
||||
|
||||
let io = WebSerialPackageIO.portIos.filter(i => i.port == port)[0];
|
||||
if (!io) {
|
||||
const options: SerialOptions = {
|
||||
baudrate: 460800,
|
||||
buffersize: 4096
|
||||
};
|
||||
io = new WebSerialPackageIO(port, options);
|
||||
WebSerialPackageIO.portIos.push(io);
|
||||
}
|
||||
return io;
|
||||
} catch (e) {
|
||||
console.log(`connection error`, e)
|
||||
}
|
||||
@@ -120,12 +128,9 @@ class WebSerialPackageIO implements pxt.HF2.PacketIO {
|
||||
});
|
||||
}
|
||||
|
||||
private closeAsync() {
|
||||
console.log(`serial: closing port`);
|
||||
this.port.close();
|
||||
this._reader = undefined;
|
||||
this._writer = undefined;
|
||||
return Promise.delay(500);
|
||||
private async closeAsync() {
|
||||
// don't close port
|
||||
return pxt.U.delay(500);
|
||||
}
|
||||
|
||||
reconnectAsync(): Promise<void> {
|
||||
@@ -141,11 +146,33 @@ class WebSerialPackageIO implements pxt.HF2.PacketIO {
|
||||
this._writer = this.port.writable.getWriter();
|
||||
return this._writer.write(pkt);
|
||||
}
|
||||
|
||||
onDeviceConnectionChanged(connect: boolean) {
|
||||
throw new Error("onDeviceConnectionChanged not implemented");
|
||||
}
|
||||
|
||||
onConnectionChanged() {
|
||||
throw new Error("onConnectionChanged not implemented");
|
||||
}
|
||||
|
||||
isConnecting() {
|
||||
throw new Error("isConnecting not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
isConnected() {
|
||||
throw new Error("isConnected not implemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
disposeAsync() {
|
||||
return Promise.reject("disposeAsync not implemented")
|
||||
}
|
||||
}
|
||||
|
||||
function hf2Async() {
|
||||
const pktIOAsync: Promise<pxt.HF2.PacketIO> = useWebSerial
|
||||
? WebSerialPackageIO.mkPacketIOAsync() : pxt.HF2.mkPacketIOAsync()
|
||||
const pktIOAsync: Promise<pxt.packetio.PacketIO> = useWebSerial
|
||||
? WebSerialPackageIO.mkPacketIOAsync() : pxt.packetio.mkPacketIOAsync()
|
||||
return pktIOAsync.then(h => {
|
||||
let w = new Ev3Wrapper(h)
|
||||
ev3 = w
|
||||
@@ -185,14 +212,19 @@ export function enableWebSerialAsync() {
|
||||
else return Promise.resolve();
|
||||
}
|
||||
|
||||
function cleanupAsync() {
|
||||
async function cleanupAsync() {
|
||||
if (ev3) {
|
||||
console.log('cleanup previous port')
|
||||
return ev3.disconnectAsync()
|
||||
.catch(e => { })
|
||||
.finally(() => { ev3 = undefined; });
|
||||
try {
|
||||
await ev3.disconnectAsync()
|
||||
}
|
||||
catch (e) {
|
||||
|
||||
}
|
||||
finally {
|
||||
ev3 = undefined;
|
||||
}
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let initPromise: Promise<Ev3Wrapper>
|
||||
@@ -202,7 +234,7 @@ function initHidAsync() { // needs to run within a click handler
|
||||
if (useHID) {
|
||||
initPromise = cleanupAsync()
|
||||
.then(() => hf2Async())
|
||||
.catch(err => {
|
||||
.catch((err: any) => {
|
||||
console.error(err);
|
||||
initPromise = null
|
||||
useHID = false;
|
||||
@@ -279,7 +311,7 @@ export function deployCoreAsync(resp: pxtc.CompileResult) {
|
||||
.catch(e => {
|
||||
// user easily forgets to stop robot
|
||||
bluetoothTryAgainAsync().then(() => w.disconnectAsync())
|
||||
.then(() => Promise.delay(1000))
|
||||
.then(() => pxt.U.delay(1000))
|
||||
.then(() => w.reconnectAsync());
|
||||
|
||||
// nothing we can do
|
||||
@@ -291,7 +323,7 @@ export function deployCoreAsync(resp: pxtc.CompileResult) {
|
||||
.then(() => w.flashAsync(elfPath, UF2.readBytes(origElfUF2, 0, origElfUF2.length * 256)))
|
||||
.then(() => w.flashAsync(rbfPath, rbfBIN))
|
||||
.then(() => w.runAsync(rbfPath))
|
||||
.then(() => Promise.delay(500))
|
||||
.then(() => pxt.U.delay(500))
|
||||
.then(() => {
|
||||
pxt.tickEvent("webserial.success");
|
||||
return w.disconnectAsync()
|
||||
|
@@ -21,7 +21,7 @@ export function bluetoothTryAgainAsync(): Promise<void> {
|
||||
|
||||
function enableWebSerialAndCompileAsync() {
|
||||
return enableWebSerialAsync()
|
||||
.then(() => Promise.delay(500))
|
||||
.then(() => pxt.U.delay(500))
|
||||
.then(() => projectView.compile());
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ function explainWebSerialPairingAsync(): Promise<void> {
|
||||
export function showUploadDialogAsync(fn: string, url: string, _confirmAsync: (options: any) => Promise<number>): Promise<void> {
|
||||
confirmAsync = _confirmAsync;
|
||||
// https://msdn.microsoft.com/en-us/library/cc848897.aspx
|
||||
// "For security reasons, data URIs are restricted to downloaded resources.
|
||||
// "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;
|
||||
@@ -126,7 +126,6 @@ export function showUploadDialogAsync(fn: string, url: string, _confirmAsync: (o
|
||||
pxt.tickEvent("bluetooth.enable");
|
||||
explainWebSerialPairingAsync()
|
||||
.then(() => enableWebSerialAndCompileAsync())
|
||||
.done();
|
||||
}
|
||||
} : undefined, downloadAgain ? {
|
||||
label: fn,
|
||||
|
@@ -26,7 +26,7 @@ export class Ev3Wrapper {
|
||||
isStreaming = false;
|
||||
dataDump = /talkdbg=1/.test(window.location.href);
|
||||
|
||||
constructor(public io: pxt.HF2.PacketIO) {
|
||||
constructor(public io: pxt.packetio.PacketIO) {
|
||||
io.onData = buf => {
|
||||
buf = buf.slice(0, HF2.read16(buf, 0) + 2)
|
||||
if (HF2.read16(buf, 4) == usbMagic) {
|
||||
@@ -81,7 +81,7 @@ export class Ev3Wrapper {
|
||||
log(`stopping PXT app`)
|
||||
let buf = this.allocCustom(2)
|
||||
return this.justSendAsync(buf)
|
||||
.then(() => Promise.delay(500))
|
||||
.then(() => pxt.U.delay(500))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ export class Ev3Wrapper {
|
||||
if (this.dataDump)
|
||||
log("TALK: " + U.toHex(buf))
|
||||
return this.io.sendPacketAsync(buf)
|
||||
.then(() => this.msgs.shiftAsync(1000))
|
||||
.then(() => this.msgs.shiftAsync(5000))
|
||||
.then(resp => {
|
||||
if (resp[2] != buf[2] || resp[3] != buf[3])
|
||||
U.userError("msg count de-sync")
|
||||
@@ -236,7 +236,7 @@ export class Ev3Wrapper {
|
||||
let contFileReq = this.allocSystem(1 + 2, 0x97)
|
||||
HF2.write16(contFileReq, 7, 1000) // maxRead
|
||||
contFileReq[6] = handle
|
||||
return Promise.delay(data.length > 0 ? 0 : 500)
|
||||
return pxt.U.delay(data.length > 0 ? 0 : 500)
|
||||
.then(() => this.talkAsync(contFileReq, -1))
|
||||
.then(resp)
|
||||
}
|
||||
@@ -251,7 +251,7 @@ export class Ev3Wrapper {
|
||||
let loop = (): Promise<void> =>
|
||||
this.lock.enqueue("file", () =>
|
||||
this.streamFileOnceAsync(path, cb))
|
||||
.then(() => Promise.delay(500))
|
||||
.then(() => pxt.U.delay(500))
|
||||
.then(loop)
|
||||
return loop()
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
|
||||
|
||||
import { FieldPorts } from "./field_ports";
|
||||
import { FieldMotors } from "./field_motors";
|
||||
import { FieldBrickButtons } from "./field_brickbuttons";
|
||||
import { FieldColorEnum } from "./field_color";
|
||||
import { FieldMusic } from "./field_music";
|
||||
@@ -14,9 +13,6 @@ pxt.editor.initFieldExtensionsAsync = function (opts: pxt.editor.FieldExtensionO
|
||||
fieldEditors: [{
|
||||
selector: "ports",
|
||||
editor: FieldPorts
|
||||
}, {
|
||||
selector: "motors",
|
||||
editor: FieldMotors
|
||||
}, {
|
||||
selector: "brickbuttons",
|
||||
editor: FieldBrickButtons
|
||||
|
@@ -64,7 +64,7 @@ export class FieldColorEnum extends pxtblockly.FieldColorNumber implements Block
|
||||
}
|
||||
this.value_ = colour;
|
||||
if (this.sourceBlock_) {
|
||||
this.sourceBlock_.setColour(colour, colour, colour);
|
||||
this.sourceBlock_.setColour(colour);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@@ -27,7 +27,6 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
|
||||
this.setText = Blockly.FieldDropdown.prototype.setText;
|
||||
this.updateSize_ = (Blockly.Field as any).prototype.updateSize_;
|
||||
this.updateTextNode_ = Blockly.Field.prototype.updateTextNode_;
|
||||
|
||||
if (!pxt.BrowserUtils.isIE() && !soundCache) {
|
||||
soundCache = JSON.parse(pxtTargetBundle.bundledpkgs['music']['sounds.jres']);
|
||||
@@ -68,7 +67,8 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
// Accessibility properties
|
||||
categoriesDiv.setAttribute('role', 'menu');
|
||||
categoriesDiv.setAttribute('aria-haspopup', 'true');
|
||||
categoriesDiv.style.backgroundColor = this.sourceBlock_.getColourTertiary();
|
||||
// FIXME: tertiary color?
|
||||
categoriesDiv.style.backgroundColor = this.sourceBlock_.getColour();
|
||||
categoriesDiv.className = 'blocklyMusicFieldCategories';
|
||||
|
||||
this.refreshCategories(categoriesDiv, categories);
|
||||
@@ -82,7 +82,9 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
dropdownDiv.appendChild(categoriesDiv);
|
||||
dropdownDiv.appendChild(contentDiv);
|
||||
|
||||
Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(), this.sourceBlock_.getColourTertiary());
|
||||
Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(),
|
||||
// FIXME: tertiary color?
|
||||
this.sourceBlock_.getColour());
|
||||
|
||||
// Calculate positioning based on the field position.
|
||||
let scale = (<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).scale;
|
||||
@@ -102,10 +104,9 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
// Update colour to look selected.
|
||||
if (this.sourceBlock_.isShadow()) {
|
||||
this.savedPrimary_ = this.sourceBlock_.getColour();
|
||||
this.sourceBlock_.setColour(this.sourceBlock_.getColourTertiary(),
|
||||
this.sourceBlock_.getColourSecondary(), this.sourceBlock_.getColourTertiary());
|
||||
} else if (this.box_) {
|
||||
this.box_.setAttribute('fill', this.sourceBlock_.getColourTertiary());
|
||||
// FIXME
|
||||
// this.sourceBlock_.setColour(this.sourceBlock_.getColourTertiary(),
|
||||
// this.sourceBlock_.getColourSecondary(), this.sourceBlock_.getColourTertiary());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +123,7 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
}
|
||||
|
||||
refreshCategories(categoriesDiv: Element, categories: string[]) {
|
||||
// Show category dropdown.
|
||||
// Show category dropdown.
|
||||
for (let i = 0; i < categories.length; i++) {
|
||||
const category = categories[i];
|
||||
|
||||
@@ -186,11 +187,13 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
let backgroundColor = this.savedPrimary_ || this.sourceBlock_.getColour();
|
||||
if (value == this.getValue()) {
|
||||
// This icon is selected, show it in a different colour
|
||||
backgroundColor = this.sourceBlock_.getColourTertiary();
|
||||
// FIXME: tertiary color?
|
||||
backgroundColor = this.sourceBlock_.getColour();
|
||||
button.setAttribute('aria-selected', 'true');
|
||||
}
|
||||
button.style.backgroundColor = backgroundColor;
|
||||
button.style.borderColor = this.sourceBlock_.getColourTertiary();
|
||||
// FIXME: tertiary color?
|
||||
button.style.borderColor = this.sourceBlock_.getColour();
|
||||
Blockly.bindEvent_(button, 'click', this, this.buttonClick_);
|
||||
Blockly.bindEvent_(button, 'mouseup', this, this.buttonClick_);
|
||||
// These are applied manually instead of using the :hover pseudoclass
|
||||
|
@@ -18,7 +18,6 @@ export class FieldPorts extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
|
||||
this.setText = Blockly.FieldDropdown.prototype.setText;
|
||||
this.updateSize_ = (Blockly.Field as any).prototype.updateSize_;
|
||||
this.updateTextNode_ = Blockly.Field.prototype.updateTextNode_;
|
||||
}
|
||||
|
||||
trimOptions_() {
|
||||
|
18
libs/base/shims.d.ts
vendored
18
libs/base/shims.d.ts
vendored
@@ -10,6 +10,12 @@ declare interface Buffer {
|
||||
//% shim=BufferMethods::getUint8
|
||||
getUint8(off: int32): int32;
|
||||
|
||||
/**
|
||||
* Returns false when the buffer can be written to.
|
||||
*/
|
||||
//% shim=BufferMethods::isReadOnly
|
||||
isReadOnly(): boolean;
|
||||
|
||||
/**
|
||||
* Writes an unsigned byte at a particular location
|
||||
*/
|
||||
@@ -81,6 +87,12 @@ declare interface Buffer {
|
||||
*/
|
||||
//% shim=BufferMethods::write
|
||||
write(dstOffset: int32, src: Buffer): void;
|
||||
|
||||
/**
|
||||
* Compute k-bit FNV-1 non-cryptographic hash of the buffer.
|
||||
*/
|
||||
//% shim=BufferMethods::hash
|
||||
hash(bits: int32): uint32;
|
||||
}
|
||||
declare namespace control {
|
||||
|
||||
@@ -88,14 +100,14 @@ declare namespace control {
|
||||
* Create a new zero-initialized buffer.
|
||||
* @param size number of bytes in the buffer
|
||||
*/
|
||||
//% shim=control::createBuffer
|
||||
//% deprecated=1 shim=control::createBuffer
|
||||
function createBuffer(size: int32): Buffer;
|
||||
|
||||
/**
|
||||
* Create a new buffer with UTF8-encoded string
|
||||
* @param str the string to put in the buffer
|
||||
*/
|
||||
//% shim=control::createBufferFromUTF8
|
||||
//% deprecated=1 shim=control::createBufferFromUTF8
|
||||
function createBufferFromUTF8(str: string): Buffer;
|
||||
}
|
||||
declare namespace loops {
|
||||
@@ -192,6 +204,8 @@ declare namespace control {
|
||||
*/
|
||||
//% shim=control::dmesgValue
|
||||
function dmesgValue(v: any): void;
|
||||
}
|
||||
declare namespace control {
|
||||
|
||||
/**
|
||||
* Force GC and dump basic information about heap.
|
||||
|
11
libs/core/cooperate.ts
Normal file
11
libs/core/cooperate.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace control {
|
||||
let lastPause = 0;
|
||||
const COOPERATION_INTERVAL = 20
|
||||
export function cooperate() {
|
||||
const now = control.millis()
|
||||
if (now - lastPause > COOPERATION_INTERVAL) {
|
||||
lastPause = now
|
||||
pause(1)
|
||||
}
|
||||
}
|
||||
}
|
@@ -21,8 +21,7 @@ namespace sensors.internal {
|
||||
const now = control.millis();
|
||||
if (now - this.lastQuery >= this.interval * 2)
|
||||
this.queryAndUpdate(); // sensor poller is not allowed to run
|
||||
if (now - this.lastPause >= this.interval * 5)
|
||||
pause(1); // allow events to trigger
|
||||
control.cooperate(); // allow events to trigger
|
||||
}
|
||||
|
||||
private queryAndUpdate() {
|
||||
|
@@ -124,7 +124,7 @@ namespace motors {
|
||||
export function stopAll() {
|
||||
const b = mkCmd(Output.ALL, DAL.opOutputStop, 0)
|
||||
writePWM(b);
|
||||
pause(1);
|
||||
control.cooperate();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,7 +136,7 @@ namespace motors {
|
||||
//% help=motors/reset-all
|
||||
export function resetAll() {
|
||||
reset(Output.ALL)
|
||||
pause(1);
|
||||
control.cooperate();
|
||||
}
|
||||
|
||||
interface MoveSchedule {
|
||||
@@ -195,7 +195,8 @@ namespace motors {
|
||||
* @param brake a value indicating if the motor should break when off
|
||||
*/
|
||||
//% blockId=outputMotorSetBrakeMode block="set %motor|brake %brake=toggleOnOff"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=60 blockGap=8
|
||||
//% group="Properties"
|
||||
//% help=motors/motor/set-brake
|
||||
@@ -209,7 +210,8 @@ namespace motors {
|
||||
* @param value true to pause; false to continue the program execution
|
||||
*/
|
||||
//% blockId=outputMotorSetPauseMode block="set %motor|pause on run %brake=toggleOnOff"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=60 blockGap=8
|
||||
//% group="Properties"
|
||||
setPauseOnRun(value: boolean) {
|
||||
@@ -217,11 +219,12 @@ namespace motors {
|
||||
this._pauseOnRun = value;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Inverts the motor polarity
|
||||
*/
|
||||
//% blockId=motorSetInverted block="set %motor|inverted %reversed=toggleOnOff"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=59 blockGap=8
|
||||
//% group="Properties"
|
||||
//% help=motors/motor/set-inverted
|
||||
@@ -234,11 +237,12 @@ namespace motors {
|
||||
return this._inverted ? -1 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Set the settle time after braking in milliseconds (default is 10ms).
|
||||
*/
|
||||
//% blockId=motorSetBrakeSettleTime block="set %motor|brake settle time %millis|ms"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=1 blockGap=8
|
||||
//% group="Properties"
|
||||
//% millis.defl=200 millis.min=0 millis.max=500
|
||||
@@ -269,7 +273,7 @@ namespace motors {
|
||||
if (this._brake && this._brakeSettleTime > 0)
|
||||
pause(this._brakeSettleTime);
|
||||
else {
|
||||
pause(1);
|
||||
control.cooperate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,7 +284,7 @@ namespace motors {
|
||||
// allow robot to settle
|
||||
this.settle();
|
||||
} else {
|
||||
pause(1);
|
||||
control.cooperate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,7 +347,8 @@ namespace motors {
|
||||
//% blockId=motorRun block="run %motor at %speed=motorSpeedPicker|\\%||for %value %unit"
|
||||
//% weight=100 blockGap=8
|
||||
//% group="Move"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% expandableArgumentMode=toggle
|
||||
//% help=motors/motor/run
|
||||
run(speed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) {
|
||||
@@ -357,7 +362,7 @@ namespace motors {
|
||||
// special: 0 is infinity
|
||||
if (schedule.steps[0] + schedule.steps[1] + schedule.steps[2] == 0) {
|
||||
this._run(schedule.speed);
|
||||
pause(1);
|
||||
control.cooperate();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -392,7 +397,8 @@ namespace motors {
|
||||
//% blockId=motorSchedule block="ramp %motor at %speed=motorSpeedPicker|\\%|for %value|%unit||accelerate %acceleration|decelerate %deceleration"
|
||||
//% weight=99 blockGap=8
|
||||
//% group="Move"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% help=motors/motor/ramp
|
||||
//% inlineInputMode=inline
|
||||
//% expandableArgumentMode=toggle
|
||||
@@ -421,7 +427,8 @@ namespace motors {
|
||||
* of run commands.
|
||||
*/
|
||||
//% blockId=outputMotorsetRunRamp block="set %motor|run %ramp to $value||$unit"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=21 blockGap=8
|
||||
//% group="Properties"
|
||||
//% help=motors/motor/set-run-phase
|
||||
@@ -492,7 +499,8 @@ namespace motors {
|
||||
* @param value true for regulated motor
|
||||
*/
|
||||
//% blockId=outputMotorSetRegulated block="set %motor|regulated %value=toggleOnOff"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=58 blockGap=8
|
||||
//% group="Properties"
|
||||
//% help=motors/motor/set-regulated
|
||||
@@ -517,7 +525,8 @@ namespace motors {
|
||||
* @param timeOut optional maximum pausing time in milliseconds
|
||||
*/
|
||||
//% blockId=motorPauseUntilRead block="pause until %motor|ready"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=90 blockGap=8
|
||||
//% group="Move"
|
||||
pauseUntilReady(timeOut?: number) {
|
||||
@@ -575,8 +584,9 @@ namespace motors {
|
||||
* @param motor the port which connects to the motor
|
||||
*/
|
||||
//% blockId=motorSpeed block="%motor|speed"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% weight=72
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=72
|
||||
//% blockGap=8
|
||||
//% group="Counters"
|
||||
//% help=motors/motor/speed
|
||||
@@ -590,21 +600,23 @@ namespace motors {
|
||||
* @param motor the port which connects to the motor
|
||||
*/
|
||||
//% blockId=motorAngle block="%motor|angle"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=70
|
||||
//% blockGap=8
|
||||
//% group="Counters"
|
||||
//% help=motors/motor/angle
|
||||
angle(): number {
|
||||
this.init();
|
||||
return getMotorData(this._port).count;
|
||||
return getMotorData(this._port).count * this.invertedFactor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the motor count
|
||||
*/
|
||||
//% blockId=motorClearCount block="clear %motor|counters"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=68
|
||||
//% blockGap=8
|
||||
//% group="Counters"
|
||||
@@ -632,7 +644,8 @@ namespace motors {
|
||||
* Pauses the program until the motor is stalled.
|
||||
*/
|
||||
//% blockId=motorPauseUntilStall block="pause until %motor|stalled"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=89
|
||||
//% group="Move"
|
||||
//% help=motors/motor/pause-until-stalled
|
||||
@@ -697,10 +710,10 @@ namespace motors {
|
||||
}
|
||||
|
||||
/**
|
||||
* The Move Tank block can make a robot drive forward, backward, turn, or stop.
|
||||
* Use the Move Tank block for robot vehicles that have two Large Motors,
|
||||
* with one motor driving the left side of the vehicle and the other the right side.
|
||||
* You can make the two motors go at different speeds or in different directions
|
||||
* The Move Tank block can make a robot drive forward, backward, turn, or stop.
|
||||
* Use the Move Tank block for robot vehicles that have two Large Motors,
|
||||
* with one motor driving the left side of the vehicle and the other the right side.
|
||||
* You can make the two motors go at different speeds or in different directions
|
||||
* to make your robot turn.
|
||||
* @param speedLeft the speed on the left motor, eg: 50
|
||||
* @param speedRight the speed on the right motor, eg: 50
|
||||
|
@@ -28,7 +28,8 @@
|
||||
"platform.h",
|
||||
"platform.cpp",
|
||||
"dmesg.cpp",
|
||||
"integrator.ts"
|
||||
"integrator.ts",
|
||||
"cooperate.ts"
|
||||
],
|
||||
"testFiles": [
|
||||
"test.ts"
|
||||
|
7
libs/core/shims.d.ts
vendored
7
libs/core/shims.d.ts
vendored
@@ -65,6 +65,13 @@ declare namespace control {
|
||||
//% help=control/allocate-notify-event shim=control::allocateNotifyEvent
|
||||
function allocateNotifyEvent(): int32;
|
||||
|
||||
/**
|
||||
* Determine the version of system software currently running.
|
||||
*/
|
||||
//% blockId="control_device_dal_version" block="device dal version"
|
||||
//% help=control/device-dal-version shim=control::deviceDalVersion
|
||||
function deviceDalVersion(): string;
|
||||
|
||||
/** Write data to DMESG debugging buffer. */
|
||||
//% shim=control::dmesg
|
||||
function dmesg(s: string): void;
|
||||
|
@@ -12,4 +12,5 @@ music.setTempo(120)
|
||||
music.noteFrequency(Note.C)
|
||||
music.beat()
|
||||
music.setVolume(50)
|
||||
```
|
||||
music.volume()
|
||||
```
|
||||
|
@@ -13,7 +13,22 @@
|
||||
|
||||
namespace music {
|
||||
|
||||
uint8_t currVolume = 50;
|
||||
int _readSystemVolume() {
|
||||
char ParBuf[8];
|
||||
int volume;
|
||||
|
||||
int fd = open("../sys/settings/Volume.rtf", O_RDONLY);
|
||||
read(fd, ParBuf, sizeof(ParBuf));
|
||||
close(fd);
|
||||
if (sscanf(ParBuf,"%d",&volume) > 0) {
|
||||
if ((volume >= 0) && (volume <= 100)) {
|
||||
return volume;
|
||||
}
|
||||
}
|
||||
return 50;
|
||||
}
|
||||
|
||||
uint8_t currVolume = _readSystemVolume();
|
||||
uint8_t *lmsSoundMMap;
|
||||
|
||||
int writeDev(void *data, int size) {
|
||||
@@ -37,6 +52,18 @@ void setVolume(int volume) {
|
||||
currVolume = max(0, min(100, volume));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the output volume of the sound synthesizer.
|
||||
*/
|
||||
//% weight=96
|
||||
//% blockId=synth_get_volume block="volume"
|
||||
//% parts="speaker" blockGap=8
|
||||
//% help=music/volume
|
||||
//% weight=1
|
||||
int volume() {
|
||||
return currVolume;
|
||||
}
|
||||
|
||||
#define SOUND_CMD_BREAK 0
|
||||
#define SOUND_CMD_TONE 1
|
||||
#define SOUND_CMD_PLAY 2
|
||||
@@ -45,7 +72,7 @@ void setVolume(int volume) {
|
||||
|
||||
struct ToneCmd {
|
||||
uint8_t cmd;
|
||||
uint8_t vol;
|
||||
uint8_t lvl;
|
||||
uint16_t freq;
|
||||
uint16_t duration;
|
||||
};
|
||||
@@ -55,10 +82,26 @@ static void _stopSound() {
|
||||
writeDev(&cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static uint8_t _getVolumeLevel(uint8_t volume, uint8_t levels) {
|
||||
uint8_t level;
|
||||
uint8_t step = (uint8_t) (100 / (levels - 1));
|
||||
if (volume < step) {
|
||||
level = 0;
|
||||
} else if (volume > step * (levels - 1)) {
|
||||
level = levels;
|
||||
} else {
|
||||
level = (uint8_t) (volume / step);
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
static void _playTone(uint16_t frequency, uint16_t duration, uint8_t volume) {
|
||||
// https://github.com/mindboards/ev3sources/blob/78ebaf5b6f8fe31cc17aa5dce0f8e4916a4fc072/lms2012/c_sound/source/c_sound.c#L471
|
||||
uint8_t level = _getVolumeLevel(volume, 13);
|
||||
|
||||
ToneCmd cmd;
|
||||
cmd.cmd = SOUND_CMD_TONE;
|
||||
cmd.vol = volume;
|
||||
cmd.lvl = level;
|
||||
cmd.freq = frequency;
|
||||
cmd.duration = duration;
|
||||
// (*SoundInstance.pSound).Busy = TRUE;
|
||||
@@ -122,7 +165,8 @@ void playSample(Buffer buf) {
|
||||
stopUser();
|
||||
pthread_mutex_lock(&pumpMutex);
|
||||
*lmsSoundMMap = 1; // BUSY
|
||||
uint8_t cmd[] = {SOUND_CMD_PLAY, (uint8_t)((currVolume / 33) + 1)};
|
||||
// https://github.com/mindboards/ev3sources/blob/78ebaf5b6f8fe31cc17aa5dce0f8e4916a4fc072/lms2012/c_sound/source/c_sound.c#L605
|
||||
uint8_t cmd[] = {SOUND_CMD_PLAY, _getVolumeLevel(currVolume, 8)};
|
||||
writeDev(cmd, 2);
|
||||
decrRC(currentSample);
|
||||
currentSample = buf;
|
||||
@@ -201,4 +245,4 @@ Buffer buffer(Sound snd) {
|
||||
void play(Sound snd) {
|
||||
music::playSample(snd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
10
libs/music/shims.d.ts
vendored
10
libs/music/shims.d.ts
vendored
@@ -13,6 +13,16 @@ declare namespace music {
|
||||
//% weight=1 shim=music::setVolume
|
||||
function setVolume(volume: int32): void;
|
||||
|
||||
/**
|
||||
* Return the output volume of the sound synthesizer.
|
||||
*/
|
||||
//% weight=96
|
||||
//% blockId=synth_get_volume block="volume"
|
||||
//% parts="speaker" blockGap=8
|
||||
//% help=music/volume
|
||||
//% weight=1 shim=music::volume
|
||||
function volume(): int32;
|
||||
|
||||
/**
|
||||
* Play a tone through the speaker for some amount of time.
|
||||
* @param frequency pitch of the tone to play in Hertz (Hz), eg: Note.C
|
||||
|
@@ -5,3 +5,4 @@ music.playTone(1440, 500)
|
||||
pause(500)
|
||||
music.playTone(2440, 500)
|
||||
pause(500)
|
||||
music.volume()
|
||||
|
25
package.json
25
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "pxt-ev3",
|
||||
"version": "1.4.19",
|
||||
"version": "1.4.25",
|
||||
"description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode",
|
||||
"private": false,
|
||||
"keywords": [
|
||||
@@ -32,21 +32,20 @@
|
||||
"docs/*/*/*.md"
|
||||
],
|
||||
"devDependencies": {
|
||||
"typescript": "2.6.1",
|
||||
"react": "16.8.3",
|
||||
"semantic-ui-less": "2.2.14",
|
||||
"@types/bluebird": "2.0.33",
|
||||
"@types/marked": "0.3.0",
|
||||
"@types/node": "8.0.53",
|
||||
"webfonts-generator": "^0.4.0",
|
||||
"@types/jquery": "3.2.16",
|
||||
"@types/react": "16.0.25",
|
||||
"@types/marked": "^0.3.0",
|
||||
"@types/node": "^9.3.0",
|
||||
"@types/react": "16.8.25",
|
||||
"@types/react-dom": "16.0.3",
|
||||
"@types/web-bluetooth": "0.0.4"
|
||||
"@types/web-bluetooth": "0.0.4",
|
||||
"@vusion/webfonts-generator": "^0.7.1",
|
||||
"react": "16.8.3",
|
||||
"react-dom": "16.11.0",
|
||||
"semantic-ui-less": "2.4.1",
|
||||
"typescript": "^4.2.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"pxt-common-packages": "6.18.2",
|
||||
"pxt-core": "5.31.8"
|
||||
"pxt-common-packages": "9.2.7",
|
||||
"pxt-core": "7.2.16"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node node_modules/pxt-core/built/pxt.js travis"
|
||||
|
@@ -77,8 +77,9 @@
|
||||
"pauseUntilBlock": {
|
||||
"category": "loops"
|
||||
},
|
||||
"bannedCategories": [
|
||||
]
|
||||
"breakBlock": true,
|
||||
"continueBlock": true,
|
||||
"bannedCategories": []
|
||||
},
|
||||
"compileService": {
|
||||
"buildEngine": "dockermake",
|
||||
@@ -114,12 +115,12 @@
|
||||
"de",
|
||||
"ja",
|
||||
"ru",
|
||||
"zh-CN"
|
||||
"zh-CN",
|
||||
"fr"
|
||||
],
|
||||
"highContrast": true,
|
||||
"lightToc": true,
|
||||
"docMenu": [
|
||||
{
|
||||
"docMenu": [{
|
||||
"name": "Support",
|
||||
"path": "https://forum.makecode.com/"
|
||||
},
|
||||
@@ -201,8 +202,8 @@
|
||||
"qrCode": true,
|
||||
"shareFinishedTutorials": true,
|
||||
"nameProjectFirst": true,
|
||||
"alwaysGithubItem": true,
|
||||
"enableTrace": true
|
||||
"enableTrace": true,
|
||||
"githubEditor": true
|
||||
},
|
||||
"ignoreDocsErrors": true,
|
||||
"uploadDocs": true
|
||||
|
@@ -1,7 +1,6 @@
|
||||
CACHE MANIFEST
|
||||
|
||||
CACHE:
|
||||
/cdn/bluebird.min.js
|
||||
/cdn/pxtsim.js
|
||||
/sim/common-sim.js
|
||||
/sim/sim.js
|
||||
|
@@ -23,7 +23,6 @@ body {
|
||||
transition: none !important;
|
||||
}
|
||||
</style>
|
||||
<script src="/cdn/bluebird.min.js"></script>
|
||||
<script src="/cdn/pxtsim.js"></script>
|
||||
<script src="/sim/common-sim.js"></script>
|
||||
<script src="/sim/sim.js"></script>
|
||||
|
5
sim/public/workerConfig.js
Normal file
5
sim/public/workerConfig.js
Normal file
@@ -0,0 +1,5 @@
|
||||
self.setSimulatorWorkerOptions({
|
||||
urls: [
|
||||
"/sim/common-sim.js"
|
||||
]
|
||||
})
|
@@ -37,7 +37,7 @@ namespace pxsim {
|
||||
return Math.round(this.angle);
|
||||
}
|
||||
|
||||
// returns the slave motor if any
|
||||
// returns the secondary motor if any
|
||||
getSynchedMotor() {
|
||||
return this._synchedMotor;
|
||||
}
|
||||
|
@@ -7,6 +7,14 @@ namespace pxsim.music {
|
||||
export function stopAllSounds() {
|
||||
SoundMethods.stop()
|
||||
}
|
||||
|
||||
pxsim.music.setVolume = (volume: number): void => {
|
||||
pxsim.getAudioState().volume = volume;
|
||||
};
|
||||
|
||||
export function volume() {
|
||||
return pxsim.getAudioState().volume;
|
||||
}
|
||||
}
|
||||
|
||||
namespace pxsim.SoundMethods {
|
||||
|
@@ -9,7 +9,7 @@
|
||||
"newLine": "LF",
|
||||
"sourceMap": false,
|
||||
"lib": ["dom", "dom.iterable", "scripthost", "es6"],
|
||||
"types": ["bluebird"],
|
||||
"types": [],
|
||||
"typeRoots": ["../node_modules/@types"]
|
||||
}
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ namespace pxsim.visuals {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.sim-button {
|
||||
cursor: pointer;
|
||||
@@ -381,7 +381,7 @@ namespace pxsim.visuals {
|
||||
this.screenCanvas = document.createElement("canvas");
|
||||
this.screenCanvas.id = "board-screen-canvas";
|
||||
this.screenCanvas.style.userSelect = "none";
|
||||
this.screenCanvas.style.msUserSelect = "none";
|
||||
(this.screenCanvas.style as any).msUserSelect = "none";
|
||||
this.screenCanvas.style.webkitUserSelect = "none";
|
||||
(this.screenCanvas.style as any).MozUserSelect = "none";
|
||||
this.screenCanvas.style.position = "absolute";
|
||||
|
@@ -17,6 +17,8 @@
|
||||
specify theme name below
|
||||
*/
|
||||
|
||||
@placeholder: 'default';
|
||||
|
||||
/* Global */
|
||||
@site : 'pxt';
|
||||
@reset : 'default';
|
||||
@@ -87,7 +89,7 @@
|
||||
Import Theme
|
||||
*******************************/
|
||||
|
||||
@import "theme.less";
|
||||
@import (multiple) "theme.less";
|
||||
|
||||
@fontPath : 'fonts';
|
||||
|
||||
|
Reference in New Issue
Block a user