Compare commits
2 Commits
v1.4.17
...
offlineapp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fd0bf92fa | ||
|
|
a33bff0520 |
@@ -1,12 +0,0 @@
|
||||
name: Compress images
|
||||
on: pull_request
|
||||
jobs:
|
||||
build:
|
||||
name: calibreapp/image-actions
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: calibreapp/image-actions
|
||||
uses: calibreapp/image-actions@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,7 +17,6 @@ clients/**/bin/**
|
||||
clients/**/obj/**
|
||||
clients/electron/projects
|
||||
libs/**/_locales/**
|
||||
package-lock.json
|
||||
|
||||
videos/**
|
||||
|
||||
|
||||
14
cmds/cmds.ts
Normal file
14
cmds/cmds.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtlib.d.ts" />
|
||||
|
||||
import * as fs from 'fs';
|
||||
|
||||
const deploy = require("./editor/deploy")
|
||||
|
||||
export function deployCoreAsync(resp: pxtc.CompileResult) {
|
||||
return deploy.deployCoreAsync(resp, process.env["PXT_SERIAL"] ? false : true)
|
||||
.then(() => {
|
||||
fs.writeFileSync("built/full-" + pxtc.BINARY_UF2, resp.outfiles[pxtc.BINARY_UF2], {
|
||||
encoding: "base64"
|
||||
})
|
||||
})
|
||||
}
|
||||
14
cmds/tsconfig.json
Normal file
14
cmds/tsconfig.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"declaration": true,
|
||||
"outDir": "../built",
|
||||
"module": "commonjs",
|
||||
"rootDir": ".",
|
||||
"newLine": "LF",
|
||||
"sourceMap": false,
|
||||
"types": ["node"]
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,13 @@
|
||||
<a class="item" href="https://makecode.com/privacy" target="_blank" rel="noopener">Privacy & Cookies</a>
|
||||
<a class="item" href="https://makecode.com/termsofuse" target="_blank" rel="noopener"> Terms Of Use</a>
|
||||
<a class="item" href="https://makecode.com/trademarks" target="_blank" rel="noopener">Trademarks</a>
|
||||
<div class="item">© 2018 Microsoft</div>
|
||||
<div class="item">©2019 Microsoft</div>
|
||||
</div>
|
||||
<div class="ui container horizontal small divided link list">
|
||||
<a class="ui centered item" href="https://makecode.com/" title="Microsoft MakeCode" target="_blank" rel="noopener">Powered by Microsoft MakeCode</a>
|
||||
</div>
|
||||
<div class="ui centered container small list">
|
||||
<p class="item">LEGO, the LEGO logo, MINDSTORMS and the MINDSTORMS EV3 logo are trademarks and/ or copyrights of the LEGO Group. ©2018 The LEGO Group. All rights reserved.</p>
|
||||
<p class="item">@copyrightText@</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
13
docs/fll.md
13
docs/fll.md
@@ -35,13 +35,6 @@ On the home page, scroll down to the **FLL / City Shaper** section for specific
|
||||
|
||||
Yes.
|
||||
|
||||
### Can I run the program again on the brick?
|
||||
|
||||

|
||||
|
||||
Use the Brick Buttons and navigate to the File Manager tab. Open the **BrkProg_SAVE** folder,
|
||||
select your program and click the center button to run it again.
|
||||
|
||||
### Does it work without internet?
|
||||
|
||||
No, the editor is cached in your browser cache. However, you can also download the [offline app](/offline-app) in case you need to install it on a computer.
|
||||
@@ -105,12 +98,6 @@ The official answer is currently no. That being said, we have **Experimental sup
|
||||
|
||||
https://youtu.be/VIq8-6Egtqs
|
||||
|
||||
## Are there YouTube videos on MakeCode for EV3?
|
||||
|
||||
The MakeCode has a [FLL / City Shaper YouTube Channel](https://www.youtube.com/watch?v=IqL0Pyeu5Ng&list=PLMMBk9hE-SeqkOObethhlZtBTEK6FYx3n) with useful videos.
|
||||
|
||||
https://youtu.be/-AirqwC9DL4
|
||||
|
||||
### Why can't I delete my program (*.uf2) files from the Brick?
|
||||
|
||||
There's a bug in the firmware which prevents you from deleting the programs (``*.uf2`` files) from your EV3 Brick. There isn't a firmware update to fix this yet.
|
||||
|
||||
@@ -73,12 +73,6 @@ Verify that the program you just created shows eyes on the Brick Display, and th
|
||||
|
||||
**Well done!**
|
||||
|
||||
## Run it Again
|
||||
|
||||

|
||||
|
||||
Use the Brick Buttons and navigate to the File Manager tab. Open the **BrkProg_SAVE** folder, select **Try** and click the center button to run it again.
|
||||
|
||||
## Connect a Large Motor @unplugged
|
||||
|
||||
Now you will learn to control the Large Motor.
|
||||
|
||||
@@ -54,12 +54,6 @@ Verify that the program you just created shows eyes on the Brick Display, and th
|
||||
|
||||
**Well done!**
|
||||
|
||||
## Run it Again
|
||||
|
||||

|
||||
|
||||
Use the Brick Buttons and navigate to the File Manager tab. Open the **BrkProg_SAVE** folder, select **Try** and click the center button to run it again.
|
||||
|
||||
## Connect a Large Motor
|
||||
|
||||
Now you will learn to control the Large Motor.
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"appref": "v1.2.26"
|
||||
"appref": "v1.2.22"
|
||||
}
|
||||
|
||||
@@ -3,11 +3,20 @@
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>LEGO® MINDSTORMS® Education EV3 Offline App</title>
|
||||
<meta name="Description" content="A MakeCode for LEGO® MINDSTORMS® Education EV3 offline app" />
|
||||
<title>@name@ Offline App</title>
|
||||
<meta name="Description" content="A MakeCode for @name@ offline app" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- @include indexhead.html -->
|
||||
<link rel="stylesheet" data-rtl="/blb/rtlsemantic.css" href="/doccdn/semantic.css" />
|
||||
<link rel="stylesheet" href="/docfiles/style.css" />
|
||||
<link rel="stylesheet" href="/docfiles/target.css" />
|
||||
|
||||
<script src="/doccdn/jquery.js" type="text/javascript"></script>
|
||||
<script src="/doccdn/semantic.js" type="text/javascript"></script>
|
||||
<script src="/docfiles/target.js" type="text/javascript"></script>
|
||||
|
||||
<style>
|
||||
@targetstyle@
|
||||
</style>
|
||||
<style>
|
||||
p.item {
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
@@ -55,6 +64,10 @@
|
||||
background-color: rgb(250, 250, 250);
|
||||
}
|
||||
|
||||
#legal-segment {
|
||||
background:white;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
.grid .column .image {
|
||||
display: none;
|
||||
@@ -368,34 +381,61 @@
|
||||
</style>
|
||||
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
tickEvent = function (id, data) {
|
||||
if (!pxt.aiTrackEvent) return;
|
||||
if (!data) pxt.aiTrackEvent(id);
|
||||
else {
|
||||
var props = {};
|
||||
var measures = {};
|
||||
for (var k in data)
|
||||
if (typeof data[k] == "string") props[k] = data[k];
|
||||
else measures[k] = data[k];
|
||||
pxt.aiTrackEvent(id, props, measures);
|
||||
}
|
||||
var electronLatestVersion = "";
|
||||
function tickEvent(id, data) {
|
||||
if (!pxt.aiTrackEvent) return;
|
||||
if (!data) pxt.aiTrackEvent(id);
|
||||
else {
|
||||
var props = {};
|
||||
var measures = {};
|
||||
for (var k in data)
|
||||
if (typeof data[k] == "string") props[k] = data[k];
|
||||
else measures[k] = data[k];
|
||||
pxt.aiTrackEvent(id, props, measures);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function agreeCheckboxChanged() {
|
||||
var downloadSegment = document.getElementById("download-segment");
|
||||
downloadSegment.classList.toggle("hidden");
|
||||
showDownloads();
|
||||
}
|
||||
|
||||
function showAgree() {
|
||||
$("#agree-segment").removeClass("hidden");
|
||||
$("#read-segment").removeClass("hidden");
|
||||
$("#legal-segment").removeClass("hidden");
|
||||
}
|
||||
|
||||
function showNoDownloads() {
|
||||
$("#no-download-segment").removeClass("hidden");
|
||||
$("#read-segment").addClass("hidden");
|
||||
$("#legal-segment").addClass("hidden");
|
||||
}
|
||||
|
||||
function showDownloads() {
|
||||
$("#download-win64").attr("href", "https://makecode.com/api/release/@targetid@/" + electronLatestVersion + "/win64");
|
||||
$("#download-mac64").attr("href", "https://makecode.com/api/release/@targetid@/" + electronLatestVersion + "/mac64");
|
||||
$("#download-segment").removeClass("hidden");
|
||||
}
|
||||
function downloadWin64() {
|
||||
// TODO: Keep this link up-to-date with the desired release version
|
||||
window.open("https://makecode.com/api/release/ev3/v1.2.26/win64");
|
||||
tickEvent("offlineapp.download", { "target": "ev3", "platform": "win64" });
|
||||
tickEvent("offlineapp.download", { "target": "@targetid@", "platform": "win64" });
|
||||
}
|
||||
function downloadMac64() {
|
||||
// TODO: Keep this link up-to-date with the desired release version
|
||||
window.open("https://makecode.com/api/release/ev3/v1.2.26/mac64");
|
||||
tickEvent("offlineapp.download", { "target": "ev3", "platform": "mac64" });
|
||||
tickEvent("offlineapp.download", { "target": "@targetid@", "platform": "mac64" });
|
||||
}
|
||||
$(function () {
|
||||
$.getJSON("https://makecode.com/api/config/@targetid@/targetconfig")
|
||||
.then(function (data) {
|
||||
if (data && data.electronManifest && data.electronManifest.latest) {
|
||||
electronLatestVersion = data.electronManifest.latest;
|
||||
showAgree();
|
||||
} else {
|
||||
showNoDownloads();
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
showNoDownloads();
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
@@ -406,35 +446,39 @@
|
||||
|
||||
<div class="ui grid topbar">
|
||||
<div class="three wide column">
|
||||
<img class="ui small image left" src="/static//lego_education_logo_white.png" />
|
||||
<img class="ui small image left" src="@cardLogo@" />
|
||||
</div>
|
||||
<div class="ten wide column">
|
||||
<h1 class="ui inverted welcomeheader">MakeCode Offline App</h1>
|
||||
<h1 class="ui inverted welcomeheader">@name@ Offline App</h1>
|
||||
</div>
|
||||
<div class="three wide column">
|
||||
<img class="ui small image right" src="/static//Microsoft-logo_rgb_c-white.png" />
|
||||
<img class="ui small image right" src="/static/Microsoft-logo_rgb_c-white.png" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui compact segments terms-container">
|
||||
<div class="ui secondary center aligned segment">
|
||||
<div id="segments" class="ui compact segments terms-container">
|
||||
<div id="read-segment" class="ui secondary center aligned segment hidden">
|
||||
Please read and accept the following terms to download the app.
|
||||
</div>
|
||||
<div class="ui left aligned segment terms">
|
||||
<div id="legal-segment" class="ui left aligned segment terms hidden">
|
||||
<div id="loader" class="ui active loader"></div>
|
||||
<div class="c17">
|
||||
<p class="c11">
|
||||
<span class="c4 c1">MICROSOFT PRE-RELEASE SOFTWARE LICENSE TERMS</span>
|
||||
</p>
|
||||
<p class="c11">
|
||||
<span class="c4 c1">MICROSOFT MAKECODE FOR LEGO MINDSTORMS EDUCATION EV3</span>
|
||||
<span class="c4 c1">MICROSOFT MAKECODE SOFTWARE FOR @name@</span>
|
||||
</p>
|
||||
<p class="c7">
|
||||
<span class="c4 c1"></span>
|
||||
</p>
|
||||
<p class="c11">
|
||||
<span class="c3 c1">These license terms are an agreement between Microsoft Corporation (or based on where you live, one
|
||||
of its affiliates) and you. They apply to the software named above. The terms also apply to any
|
||||
Microsoft services or updates for the software, except to the extent those have additional terms.</span>
|
||||
<span class="c3 c1">These license terms are an agreement between Microsoft Corporation (or based
|
||||
on where you live, one
|
||||
of its affiliates) and you. They apply to the software named above. The terms also apply to
|
||||
any
|
||||
Microsoft services or updates for the software, except to the extent those have additional
|
||||
terms.</span>
|
||||
</p>
|
||||
<p class="c7">
|
||||
<span class="c3 c1"></span>
|
||||
@@ -446,27 +490,35 @@
|
||||
<span class="c5 c1">1.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">INSTALLATION AND USE RIGHTS. </span>
|
||||
<span class="c3 c1">You may install and use any number of copies of the software to evaluate it as you develop and test
|
||||
your software applications for use with Lego Mindstorms Education EV3 hardware.</span>
|
||||
<span class="c3 c1">You may install and use any number of copies of the software to evaluate it
|
||||
as you develop and test
|
||||
your software applications for use with @name@ hardware.</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
<span class="c5 c1">2.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">PRE-RELEASE SOFTWARE. </span>
|
||||
<span class="c3 c1">The software is a pre-release version. It may not work the way a final version of the software will.
|
||||
Microsoft may change it for the final, commercial version. We also may not release a commercial
|
||||
version. Microsoft is not obligated to provide maintenance, technical support or updates to you
|
||||
<span class="c3 c1">The software is a pre-release version. It may not work the way a final
|
||||
version of the software will.
|
||||
Microsoft may change it for the final, commercial version. We also may not release a
|
||||
commercial
|
||||
version. Microsoft is not obligated to provide maintenance, technical support or updates to
|
||||
you
|
||||
for the software.</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
<span class="c5 c1">3.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">ASSOCIATED ONLINE SERVICES.</span>
|
||||
<span class="c1"> Some features of the software provide access
|
||||
to, or rely on, online services to provide you information about updates to the software or extensions,
|
||||
or to enable you to retrieve content, collaborate with others, or otherwise supplement your development
|
||||
experience. As used throughout these license terms, the term <q>software</q> includes these online
|
||||
services and features. By using these online services and features you consent to the to the
|
||||
<span class="c1"> Some features of the software
|
||||
provide access
|
||||
to, or rely on, online services to provide you information about updates to the software or
|
||||
extensions,
|
||||
or to enable you to retrieve content, collaborate with others, or otherwise supplement your
|
||||
development
|
||||
experience. As used throughout these license terms, the term <q>software</q> includes these
|
||||
online
|
||||
services and features. By using these online services and features you consent to the to the
|
||||
transmission of information as described in Section 5, DATA.
|
||||
</span>
|
||||
</p>
|
||||
@@ -474,9 +526,11 @@
|
||||
<span class="c5 c1">4.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">LICENSES FOR OTHER COMPONENTS.</span>
|
||||
<span class="c3 c1"> The software may include third party components with separate legal notices or governed by
|
||||
<span class="c3 c1"> The software may include third party components with separate legal
|
||||
notices or governed by
|
||||
other agreements, as described in the ThirdPartyNotices file accompanying the software. Even
|
||||
if such components are governed by other agreements, the disclaimers and the limitations on and
|
||||
if such components are governed by other agreements, the disclaimers and the limitations on
|
||||
and
|
||||
exclusions of damages below also apply.</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
@@ -488,26 +542,35 @@
|
||||
<span class="c5 c1">a.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c1 c5">Data Collection. </span>
|
||||
<span class="c1">The software may collect information about you and your use of the software, and send that to Microsoft.
|
||||
Microsoft may use this information to provide services and improve our products and services.
|
||||
You may opt out of many of these scenarios, but not all, as described in the product documentation.
|
||||
In using the software, you must comply with applicable law. You can learn more about data collection
|
||||
<span class="c1">The software may collect information about you and your use of the software,
|
||||
and send that to Microsoft.
|
||||
Microsoft may use this information to provide services and improve our products and
|
||||
services.
|
||||
You may opt out of many of these scenarios, but not all, as described in the product
|
||||
documentation.
|
||||
In using the software, you must comply with applicable law. You can learn more about data
|
||||
collection
|
||||
and use in the help documentation and the privacy statement at </span>
|
||||
<span class="c14 c1">
|
||||
<a class="c9" href="http://go.microsoft.com/fwlink/?LinkId=398505">http://go.microsoft.com/fwlink/?LinkId=398505</a>
|
||||
<a class="c9"
|
||||
href="http://go.microsoft.com/fwlink/?LinkId=398505">http://go.microsoft.com/fwlink/?LinkId=398505</a>
|
||||
</span>
|
||||
<span class="c1">.</span>
|
||||
<span class="c3 c1"> Your use of the software operates as your consent to these practices.</span>
|
||||
<span class="c3 c1"> Your use of the software operates as your consent to these
|
||||
practices.</span>
|
||||
</p>
|
||||
<p class="c8">
|
||||
<span class="c5 c1">b.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">Processing of Personal Data. </span>
|
||||
<span class="c1">To the extent Microsoft is a processor or subprocessor of personal data in connection with the software,
|
||||
Microsoft makes the commitments in the European Union General Data Protection Regulation Terms
|
||||
<span class="c1">To the extent Microsoft is a processor or subprocessor of personal data in
|
||||
connection with the software,
|
||||
Microsoft makes the commitments in the European Union General Data Protection Regulation
|
||||
Terms
|
||||
of the Online Services Terms to all customers effective May 25, 2018, at </span>
|
||||
<span class="c1 c14">
|
||||
<a class="c9" href="http://go.microsoft.com/?linkid=9840733">http://go.microsoft.com/?linkid=9840733</a>
|
||||
<a class="c9"
|
||||
href="http://go.microsoft.com/?linkid=9840733">http://go.microsoft.com/?linkid=9840733</a>
|
||||
</span>
|
||||
<span class="c3 c1">.</span>
|
||||
</p>
|
||||
@@ -515,48 +578,62 @@
|
||||
<span class="c5 c1">6.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">FEEDBACK. </span>
|
||||
<span class="c3 c1">If you give feedback about the software to Microsoft, you give to Microsoft, without charge, the
|
||||
<span class="c3 c1">If you give feedback about the software to Microsoft, you give to Microsoft,
|
||||
without charge, the
|
||||
right to use, share and commercialize your feedback in any way and for any purpose. You will
|
||||
not give feedback that is subject to a license that requires Microsoft to license its software
|
||||
or documentation to third parties because we include your feedback in them. These rights survive
|
||||
not give feedback that is subject to a license that requires Microsoft to license its
|
||||
software
|
||||
or documentation to third parties because we include your feedback in them. These rights
|
||||
survive
|
||||
this agreement.</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
<span class="c5 c1">7.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">SCOPE OF LICENSE.</span>
|
||||
<span class="c3 c1"> The software is licensed, not sold. This agreement only gives you some rights to use the software.
|
||||
Microsoft reserves all other rights. Unless applicable law gives you more rights despite this
|
||||
<span class="c3 c1"> The software is licensed, not sold. This agreement only gives you some
|
||||
rights to use the software.
|
||||
Microsoft reserves all other rights. Unless applicable law gives you more rights despite
|
||||
this
|
||||
limitation, you may use the software only as expressly permitted in this agreement. In
|
||||
doing so, you must comply with any technical limitations in the software that only allow you
|
||||
to use it in certain ways. You may not:</span>
|
||||
</p>
|
||||
<p class="c8">
|
||||
<span class="c3 c1">- work around any technical limitations in the software;</span>
|
||||
<span class="c3 c1">- work around any technical limitations in the
|
||||
software;</span>
|
||||
</p>
|
||||
<p class="c8">
|
||||
<span class="c3 c1">- reverse engineer, decompile or disassemble the software, or attempt to do so, except
|
||||
<span class="c3 c1">- reverse engineer, decompile or disassemble the software, or
|
||||
attempt to do so, except
|
||||
and only to the extent required by third party licensing terms governing use of certain open
|
||||
source components that may be included with the software;</span>
|
||||
</p>
|
||||
<p class="c8">
|
||||
<span class="c3 c1">- remove, minimize, block or modify any notices of Microsoft or its suppliers in the
|
||||
<span class="c3 c1">- remove, minimize, block or modify any notices of Microsoft
|
||||
or its suppliers in the
|
||||
software;
|
||||
</span>
|
||||
</p>
|
||||
<p class="c8">
|
||||
<span class="c3 c1">- use the software in any way that is against the law; or</span>
|
||||
<span class="c3 c1">- use the software in any way that is against the law;
|
||||
or</span>
|
||||
</p>
|
||||
<p class="c8">
|
||||
<span class="c3 c1">- share, publish, rent or lease the software, or provide the software as a stand-alone
|
||||
<span class="c3 c1">- share, publish, rent or lease the software, or provide the
|
||||
software as a stand-alone
|
||||
offering for others to use.</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
<span class="c5 c1">8. UPDATES. </span>
|
||||
<span class="c3 c1">The software may periodically check for updates and download and install them for you. You may obtain
|
||||
updates only from Microsoft or authorized sources. Microsoft may need to update your system to
|
||||
provide you with updates. You agree to receive these automatic updates without any additional
|
||||
notice. Updates may not include or support all existing software features, services, or peripheral
|
||||
<span class="c3 c1">The software may periodically check for updates and download and install
|
||||
them for you. You may obtain
|
||||
updates only from Microsoft or authorized sources. Microsoft may need to update your system
|
||||
to
|
||||
provide you with updates. You agree to receive these automatic updates without any
|
||||
additional
|
||||
notice. Updates may not include or support all existing software features, services, or
|
||||
peripheral
|
||||
devices.
|
||||
</span>
|
||||
</p>
|
||||
@@ -564,57 +641,74 @@
|
||||
<span class="c5 c1">9.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">EXPORT RESTRICTIONS.</span>
|
||||
<span class="c3 c1"> You must comply with all domestic and international export laws and regulations that apply
|
||||
to the software, which include restrictions on destinations, end users and end use. For further
|
||||
<span class="c3 c1"> You must comply with all domestic and international export laws and
|
||||
regulations that apply
|
||||
to the software, which include restrictions on destinations, end users and end use. For
|
||||
further
|
||||
information on export restrictions, visit (aka.ms/exporting).</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
<span class="c5 c1">10.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">SUPPORT SERVICES. </span>
|
||||
<span class="c3 c1">Because the software is “as is,” we may not provide support services for it.</span>
|
||||
<span class="c3 c1">Because the software is “as is,” we may not provide support
|
||||
services for it.</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
<span class="c5 c1">11.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">ENTIRE AGREEMENT.</span>
|
||||
<span class="c3 c1"> This agreement, and the terms for supplements, updates, Internet-based services and support
|
||||
services that you use, are the entire agreement for the software and support services.</span>
|
||||
<span class="c3 c1"> This agreement, and the terms for supplements, updates, Internet-based
|
||||
services and support
|
||||
services that you use, are the entire agreement for the software and support
|
||||
services.</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
<span class="c5 c1">12.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">APPLICABLE LAW. </span>
|
||||
<span class="c3 c1">If you acquired the software in the United States, Washington State law applies to interpretation
|
||||
of and claims for breach of this agreement, and the laws of the state where you live apply to
|
||||
<span class="c3 c1">If you acquired the software in the United States, Washington State law
|
||||
applies to interpretation
|
||||
of and claims for breach of this agreement, and the laws of the state where you live apply
|
||||
to
|
||||
all other claims. If you acquired the software in any other country, its laws apply.</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
<span class="c5 c1">13.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">CONSUMER RIGHTS; REGIONAL VARIATIONS. </span>
|
||||
<span class="c3 c1">This agreement describes certain legal rights. You may have other rights, including consumer rights,
|
||||
under the laws of your state or country. Separate and apart from your relationship with Microsoft,
|
||||
you may also have rights with respect to the party from which you acquired the software. This
|
||||
agreement does not change those other rights if the laws of your state or country do not permit
|
||||
it to do so. For example, if you acquired the software in one of the below regions, or mandatory
|
||||
<span class="c3 c1">This agreement describes certain legal rights. You may have other rights,
|
||||
including consumer rights,
|
||||
under the laws of your state or country. Separate and apart from your relationship with
|
||||
Microsoft,
|
||||
you may also have rights with respect to the party from which you acquired the software.
|
||||
This
|
||||
agreement does not change those other rights if the laws of your state or country do not
|
||||
permit
|
||||
it to do so. For example, if you acquired the software in one of the below regions, or
|
||||
mandatory
|
||||
country law applies, then the following provisions apply to you:</span>
|
||||
</p>
|
||||
<p class="c8">
|
||||
<span class="c5 c1">a.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">Australia. </span>
|
||||
<span class="c3 c1">You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is
|
||||
<span class="c3 c1">You have statutory guarantees under the Australian Consumer Law and nothing
|
||||
in this agreement is
|
||||
intended to affect those rights.</span>
|
||||
</p>
|
||||
<p class="c8">
|
||||
<span class="c5 c1">b.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">Canada. </span>
|
||||
<span class="c3 c1">If you acquired the software in Canada, you may stop receiving updates by turning off the automatic
|
||||
update feature, disconnecting your device from the Internet (if and when you re-connect to the
|
||||
Internet, however, the software will resume checking for and installing updates), or uninstalling
|
||||
the software. The product documentation, if any, may also specify how to turn off updates for
|
||||
<span class="c3 c1">If you acquired the software in Canada, you may stop receiving updates by
|
||||
turning off the automatic
|
||||
update feature, disconnecting your device from the Internet (if and when you re-connect to
|
||||
the
|
||||
Internet, however, the software will resume checking for and installing updates), or
|
||||
uninstalling
|
||||
the software. The product documentation, if any, may also specify how to turn off updates
|
||||
for
|
||||
your specific device or software.</span>
|
||||
</p>
|
||||
<p class="c8">
|
||||
@@ -627,8 +721,10 @@
|
||||
<span class="c5 c1">(i)</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">Warranty</span>
|
||||
<span class="c3 c1">. The properly licensed software will perform substantially as described in any Microsoft materials
|
||||
that accompany the software. However, Microsoft gives no contractual guarantee in relation to
|
||||
<span class="c3 c1">. The properly licensed software will perform substantially as described in
|
||||
any Microsoft materials
|
||||
that accompany the software. However, Microsoft gives no contractual guarantee in relation
|
||||
to
|
||||
the licensed software.</span>
|
||||
</p>
|
||||
<p class="c6">
|
||||
@@ -638,74 +734,103 @@
|
||||
<span class="c5 c1">(ii)</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">Limitation of Liability</span>
|
||||
<span class="c3 c1">. In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as
|
||||
well as, in case of death or personal or physical injury, Microsoft is liable according to the
|
||||
<span class="c3 c1">. In case of intentional conduct, gross negligence, claims based on the
|
||||
Product Liability Act, as
|
||||
well as, in case of death or personal or physical injury, Microsoft is liable according to
|
||||
the
|
||||
statutory law.</span>
|
||||
</p>
|
||||
<p class="c10">
|
||||
<span class="c3 c1">Subject to the foregoing clause (ii), Microsoft will only be liable for slight negligence if Microsoft
|
||||
is in breach of such material contractual obligations, the fulfillment of which facilitate the
|
||||
due performance of this agreement, the breach of which would endanger the purpose of this agreement
|
||||
and the compliance with which a party may constantly trust in (so-called "cardinal obligations").
|
||||
In other cases of slight negligence, Microsoft will not be liable for slight negligence.</span>
|
||||
<span class="c3 c1">Subject to the foregoing clause (ii), Microsoft will only be liable for
|
||||
slight negligence if Microsoft
|
||||
is in breach of such material contractual obligations, the fulfillment of which facilitate
|
||||
the
|
||||
due performance of this agreement, the breach of which would endanger the purpose of this
|
||||
agreement
|
||||
and the compliance with which a party may constantly trust in (so-called "cardinal
|
||||
obligations").
|
||||
In other cases of slight negligence, Microsoft will not be liable for slight
|
||||
negligence.</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
<span class="c5 c1">14.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c5 c1">LEGAL EFFECT.</span>
|
||||
<span class="c3 c1"> This agreement describes certain legal rights. You may have other rights under the laws of
|
||||
your country. You may also have rights with respect to the party from whom you acquired the software.
|
||||
This agreement does not change your rights under the laws of your country if the laws of your
|
||||
<span class="c3 c1"> This agreement describes certain legal rights. You may have other
|
||||
rights under the laws of
|
||||
your country. You may also have rights with respect to the party from whom you acquired the
|
||||
software.
|
||||
This agreement does not change your rights under the laws of your country if the laws of
|
||||
your
|
||||
country do not permit it to do so.</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
<span class="c5 c1">15.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c4 c1">DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS-IS.” YOU BEAR THE RISK OF
|
||||
USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR CONDITIONS. TO THE EXTENT PERMITTED
|
||||
<span class="c4 c1">DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS-IS.”
|
||||
YOU BEAR THE RISK OF
|
||||
USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR CONDITIONS. TO THE EXTENT
|
||||
PERMITTED
|
||||
UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
<span class="c5 c1">16.</span>
|
||||
<span class="c1"> </span>
|
||||
<span class="c4 c1">LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT
|
||||
DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST
|
||||
<span class="c4 c1">LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM MICROSOFT AND
|
||||
ITS SUPPLIERS ONLY DIRECT
|
||||
DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL,
|
||||
LOST
|
||||
PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.</span>
|
||||
</p>
|
||||
<p class="c0">
|
||||
<span class="c3 c1">This limitation applies to (a) anything related to the software, services, content (including code)
|
||||
on third party Internet sites, or third party programs; and (b) claims for breach of contract,
|
||||
breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the
|
||||
<span class="c3 c1">This limitation applies to (a) anything related to the software, services,
|
||||
content (including code)
|
||||
on third party Internet sites, or third party programs; and (b) claims for breach of
|
||||
contract,
|
||||
breach of warranty, guarantee or condition, strict liability, negligence, or other tort to
|
||||
the
|
||||
extent permitted by applicable law.</span>
|
||||
</p>
|
||||
<p class="c0">
|
||||
<span class="c3 c1">It also applies even if Microsoft knew or should have known about the possibility of the damages.
|
||||
The above limitation or exclusion may not apply to you because your country may not allow the
|
||||
<span class="c3 c1">It also applies even if Microsoft knew or should have known about the
|
||||
possibility of the damages.
|
||||
The above limitation or exclusion may not apply to you because your country may not allow
|
||||
the
|
||||
exclusion or limitation of incidental, consequential or other damages.</span>
|
||||
</p>
|
||||
<p class="c12">
|
||||
<span class="c4 c1">Please note: As the software is distributed in Quebec, Canada, some of the clauses in this agreement
|
||||
<span class="c4 c1">Please note: As the software is distributed in Quebec, Canada, some of the
|
||||
clauses in this agreement
|
||||
are provided below in French.</span>
|
||||
</p>
|
||||
<p class="c12">
|
||||
<span class="c4 c1">Remarque : Ce logiciel étant distribué au Québec, Canada, certaines des clauses
|
||||
<span class="c4 c1">Remarque : Ce logiciel étant distribué au Québec,
|
||||
Canada, certaines des clauses
|
||||
dans ce contrat sont fournies ci-dessous en français.</span>
|
||||
</p>
|
||||
<p class="c11">
|
||||
<span class="c5 c1">EXONÉRATION DE GARANTIE.</span>
|
||||
<span class="c1 c3"> Le logiciel visé par une licence est offert « tel quel ». Toute utilisation
|
||||
de ce logiciel est à votre seule risque et péril. Microsoft n’accorde aucune
|
||||
autre garantie expresse. Vous pouvez bénéficier de droits additionnels en vertu
|
||||
du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles
|
||||
sont permises par le droit locale, les garanties implicites de qualité marchande, d’adéquation
|
||||
<span class="c1 c3"> Le logiciel visé par une licence est offert « tel quel
|
||||
». Toute utilisation
|
||||
de ce logiciel est à votre seule risque et péril. Microsoft n’accorde
|
||||
aucune
|
||||
autre garantie expresse. Vous pouvez bénéficier de droits additionnels en
|
||||
vertu
|
||||
du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou
|
||||
elles
|
||||
sont permises par le droit locale, les garanties implicites de qualité marchande,
|
||||
d’adéquation
|
||||
à un usage particulier et d’absence de contrefaçon sont exclues.
|
||||
</span>
|
||||
</p>
|
||||
<p class="c11">
|
||||
<span class="c5 c1">LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES DOMMAGES.</span>
|
||||
<span class="c3 c1"> Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages
|
||||
directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune
|
||||
<span class="c5 c1">LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE
|
||||
RESPONSABILITÉ POUR LES DOMMAGES.</span>
|
||||
<span class="c3 c1"> Vous pouvez obtenir de Microsoft et de ses fournisseurs une
|
||||
indemnisation en cas de dommages
|
||||
directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à
|
||||
aucune
|
||||
indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou
|
||||
accessoires et pertes de bénéfices.</span>
|
||||
</p>
|
||||
@@ -713,26 +838,36 @@
|
||||
<span class="c3 c1">Cette limitation concerne :</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
<span class="c3 c1">- tout ce qui est relié au logiciel, aux services ou au contenu
|
||||
(y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ; et</span>
|
||||
<span class="c3 c1">- tout ce qui est relié au logiciel, aux
|
||||
services ou au contenu
|
||||
(y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers ;
|
||||
et</span>
|
||||
</p>
|
||||
<p class="c2">
|
||||
<span class="c3 c1">- les réclamations au titre de violation de contrat ou de garantie,
|
||||
ou au titre de responsabilité stricte, de négligence ou d’une autre faute
|
||||
<span class="c3 c1">- les réclamations au titre de violation
|
||||
de contrat ou de garantie,
|
||||
ou au titre de responsabilité stricte, de négligence ou d’une autre
|
||||
faute
|
||||
dans la limite autorisée par la loi en vigueur.</span>
|
||||
</p>
|
||||
<p class="c12">
|
||||
<span class="c3 c1">Elle s’applique également, même si Microsoft connaissait ou devrait connaître
|
||||
<span class="c3 c1">Elle s’applique également, même si Microsoft connaissait
|
||||
ou devrait connaître
|
||||
l’éventualité d’un tel dommage. Si votre pays n’autorise pas
|
||||
l’exclusion ou la limitation de responsabilité pour les dommages indirects, accessoires
|
||||
ou de quelque nature que ce soit, il se peut que la limitation ou l’exclusion ci-dessus
|
||||
l’exclusion ou la limitation de responsabilité pour les dommages indirects,
|
||||
accessoires
|
||||
ou de quelque nature que ce soit, il se peut que la limitation ou l’exclusion
|
||||
ci-dessus
|
||||
ne s’appliquera pas à votre égard.</span>
|
||||
</p>
|
||||
<p class="c16">
|
||||
<span class="c5 c1">EFFET JURIDIQUE.</span>
|
||||
<span class="c3 c1"> Le présent contrat décrit certains droits juridiques. Vous pourriez avoir d’autres
|
||||
droits prévus par les lois de votre pays. Le présent contrat ne modifie pas les
|
||||
droits que vous confèrent les lois de votre pays si celles-ci ne le permettent pas.</span>
|
||||
<span class="c3 c1"> Le présent contrat décrit certains droits juridiques.
|
||||
Vous pourriez avoir d’autres
|
||||
droits prévus par les lois de votre pays. Le présent contrat ne modifie pas
|
||||
les
|
||||
droits que vous confèrent les lois de votre pays si celles-ci ne le permettent
|
||||
pas.</span>
|
||||
</p>
|
||||
<p class="c15">
|
||||
<span class="c3 c1"></span>
|
||||
@@ -740,9 +875,9 @@
|
||||
<p class="c16">
|
||||
<span class="c3 c1"> </span>
|
||||
</p>
|
||||
|
||||
<p class="c11">
|
||||
<span class="c3 c1">LEGO, the LEGO logo, MINDSTORMS and the MINDSTORMS EV3 logo are trademarks and/ or copyrights of
|
||||
the LEGO Group. ©2018 The LEGO Group. All rights reserved.</span>
|
||||
<span class="c3 c1">@copyrightText@</span>
|
||||
</p>
|
||||
<p class="c11">
|
||||
<span class="c3 c1"> </span>
|
||||
@@ -755,27 +890,30 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui center aligned segment">
|
||||
<div id="agree-segment" class="ui center aligned segment hidden">
|
||||
<input id="agree-checkbox" type="checkbox" autocomplete="off" onchange="agreeCheckboxChanged(this)">
|
||||
<label for="agree-checkbox">I agree to these Microsoft Software License Terms and to the
|
||||
<a href="https://privacy.microsoft.com/en-us/privacystatement">Microsoft Privacy Statement.</a>
|
||||
</label>
|
||||
</div>
|
||||
<div id="no-download-segment" class="ui center aligned segment hidden">
|
||||
<p>Sorry, there is no Offline App available for this editor.</p>
|
||||
</div>
|
||||
<div id="download-segment" class="ui center aligned segment hidden">
|
||||
<div class="ui grid">
|
||||
<div class="eight wide column">
|
||||
<h3 class="ui">Windows</h3>
|
||||
<button class="ui icon button" onclick="downloadWin64()">
|
||||
<a id="download-win64" class="ui icon button" onclick="downloadWin64()">
|
||||
<i class="download icon"></i>
|
||||
makecode-ev3-setup-win64.exe
|
||||
</button>
|
||||
makecode-@targetid@-setup-win64.exe
|
||||
</a>
|
||||
</div>
|
||||
<div class="eight wide column">
|
||||
<h3 class="ui">Mac OS</h3>
|
||||
<button class="ui icon button" onclick="downloadMac64()">
|
||||
<a id="download-mac64" class="ui icon button" onclick="downloadMac64()">
|
||||
<i class="download icon"></i>
|
||||
makecode-ev3-mac64.zip
|
||||
</button>
|
||||
makecode-@targetid@-mac64.zip
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -788,4 +926,4 @@
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
@@ -1,88 +1,9 @@
|
||||
# Projects
|
||||
|
||||
```codecard
|
||||
[
|
||||
{
|
||||
"name": "Getting Started",
|
||||
"url": "/getting-started",
|
||||
"imageUrl": "/static/lessons/firmware.png"
|
||||
},
|
||||
{
|
||||
"name": "Brick Tutorials",
|
||||
"url": "/tutorials/brick",
|
||||
"imageUrl": "/static/tutorials/wake-up.png"
|
||||
},
|
||||
{
|
||||
"name": "Motor Tutorials",
|
||||
"url": "/tutorials/motors",
|
||||
"imageUrl": "/static/tutorials/run-motors.png"
|
||||
},
|
||||
{
|
||||
"name": "Touch Sensor Tutorials",
|
||||
"url": "/tutorials/touch-sensor",
|
||||
"imageUrl": "/static/tutorials/touch-to-run.png"
|
||||
},
|
||||
{
|
||||
"name": "Color Sensor Tutorials",
|
||||
"url": "/tutorials/color-sensor",
|
||||
"imageUrl": "/static/tutorials/what-color.png"
|
||||
},
|
||||
{
|
||||
"name": "Ultrasonic Sensor Tutorials",
|
||||
"url": "/tutorials/ultrasonic-sensor",
|
||||
"imageUrl": "/static/tutorials/object-near.png"
|
||||
},
|
||||
{
|
||||
"name": "Gyro Tutorials",
|
||||
"url": "/tutorials/gyro",
|
||||
"imageUrl": "/static/tutorials/calibrate-gyro.png"
|
||||
},
|
||||
{
|
||||
"name": "Infrared Sensor Tutorials",
|
||||
"url": "/tutorials/infrared-sensor",
|
||||
"imageUrl": "/static/tutorials/security-alert.png"
|
||||
},
|
||||
{
|
||||
"name": "FLL / City Shaper",
|
||||
"url": "/tutorials/city-shaper",
|
||||
"imageUrl": "/static/tutorials/city-shaper/robot1.jpg"
|
||||
},
|
||||
{
|
||||
"name": "Design Engineering",
|
||||
"url": "/design-engineering",
|
||||
"imageUrl": "/static/lessons/make-it-move-without-wheels.png"
|
||||
},
|
||||
{
|
||||
"name": "Coding",
|
||||
"url": "/coding",
|
||||
"imageUrl": "/static/lessons/autonomous-parking.png"
|
||||
},
|
||||
{
|
||||
"name": "Maker",
|
||||
"url": "/maker",
|
||||
"imageUrl": "/static/lessons/make-a-sound-machine.png"
|
||||
},
|
||||
{
|
||||
"name": "Tutorial Videos",
|
||||
"url": "/videos",
|
||||
"imageUrl": "https://legoeducation.videomarketingplatform.co/27288170/35719444/5d009e5f93fbf479c2e5ed2bf87a7990/thumbnail.png"
|
||||
}
|
||||
]
|
||||
```
|
||||
Here are some cool projects that you can build with your @boardname@!
|
||||
|
||||
## See Also
|
||||
## Basic
|
||||
|
||||
[Getting Started](/getting-started),
|
||||
[Brick Tutorials](/tutorials/brick),
|
||||
[Motor Tutorials](/tutorials/motors),
|
||||
[Touch Sensor Tutorials](/tutorials/touch-sensor),
|
||||
[Color Sensor Tutorials](/tutorials/color-sensor),
|
||||
[Ultrasonic Sensor Tutorials](/tutorials/ultrasonic-sensor),
|
||||
[Gyro Tutorials](/tutorials/gyro),
|
||||
[Infrared Sensor Tutorials](/tutorials/infrared-sensor),
|
||||
[FLL / City Shaper](/tutorials/city-shaper),
|
||||
[Design Engineering](/design-engineering),
|
||||
[Coding](/coding),
|
||||
[Maker](/maker),
|
||||
[Tutorial Videos](/videos)
|
||||
Basic projects to build with your EV3 Brick.
|
||||
|
||||
Coming soon.
|
||||
@@ -1,69 +0,0 @@
|
||||
# Projects
|
||||
|
||||
* [Getting Started](/getting-started)
|
||||
* [Prepare](https://makecode.mindstorms.com/troubleshoot)
|
||||
* [Try](/getting-started/try)
|
||||
* [Use](/getting-started/use)
|
||||
* [First LEGO League](/fll)
|
||||
* [Brick Tutorials](/tutorials/brick)
|
||||
* [Wake Up!](/tutorials/wake-up)
|
||||
* [Make an Animation](/tutorials/make-an-animation)
|
||||
* [What Animal Am I?](/tutorials/what-animal-am-i)
|
||||
* [Music Brick](/tutorials/music-brick)
|
||||
* [Pause On Start](/tutorials/pause-on-start)
|
||||
* [Motor Tutorials](/tutorials/motors)
|
||||
* [Run Motors](/tutorials/run-motors)
|
||||
* [Spin Turn](/tutorials/spin-turn)
|
||||
* [Pivot Turn](/tutorials/pivot-turn)
|
||||
* [Smooth Turn](/tutorials/smooth-turn)
|
||||
* [Tank ZigZag](/tutorials/tank-zigzag)
|
||||
* [Coast Or Brake](/tutorials/coast-or-brake)
|
||||
* [Turtle](/tutorials/turtle)
|
||||
* [Touch Sensor Tutorials](/tutorials/touch-sensor)
|
||||
* [Touch to Run](/tutorials/touch-to-run)
|
||||
* [Sensor Values](/tutorials/touch-sensor-values)
|
||||
* [Stop At Object](/tutorials/stop-at-object)
|
||||
* [Color Sensor Tutorials](/tutorials/color-sensor)
|
||||
* [What Color?](/tutorials/what-color)
|
||||
* [Line Following](/tutorials/line-following)
|
||||
* [Red Light, Green Light](/tutorials/redlight-greenlight)
|
||||
* [Move To Color](/tutorials/move-to-color)
|
||||
* [Reflected Light Measure](/tutorials/reflected-light-measure)
|
||||
* [Reflected Light Calibration](/tutorials/reflected-light-calibration)
|
||||
* [Ultrasonic Sensor Tutorials](/tutorials/ultrasonic-sensor)
|
||||
* [Object Near](/tutorials/object-near)
|
||||
* [Wall Follower](/tutorials/wall-follower)
|
||||
* [Gyro Tutorials](/tutorials/gyro)
|
||||
* [Calibrate](/tutorials/calibrate-gyro)
|
||||
* [Turn](/tutorials/turn-with-gyro)
|
||||
* [Move Straight](/tutorials/move-straight-with-gyro)
|
||||
* [Drifter](/tutorials/drifter)
|
||||
* [Infrared Sensor Tutorials](/tutorials/infrared-sensor)
|
||||
* [Security Alert](/tutorials/security-alert)
|
||||
* [FLL / City Shaper](/tutorials/city-shaper)
|
||||
* [Crane Mission / Robot 1](/tutorials/city-shaper/robot-1)
|
||||
* [Crane Mission / Robot 2](/tutorials/city-shaper/robot-2)
|
||||
* [Crane Mission / Video 1](https://youtu.be/IqL0Pyeu5Ng)
|
||||
* [Bluetooth download (beta)](https://youtu.be/VIq8-6Egtqs)
|
||||
* [Turn with Gyro](https://youtu.be/I7ncuXAfBwk)
|
||||
* [Moving with Gyro](https://youtu.be/ufiOPvW37xc)
|
||||
* [Line following with 1 color sensor](https://youtu.be/_LeduyKQVjg)
|
||||
* [Proportional line following with 1 color sensor](https://youtu.be/-AirqwC9DL4)
|
||||
* [Proportional line following with 2 color sensors](https://youtu.be/QWOflBuu9Oo)
|
||||
* [Design Engineering](/design-engineering)
|
||||
* [Make It Move Without Wheels](/design-engineering/make-it-move)
|
||||
* [Make It Smarter and Faster](/design-engineering/make-it-smarter)
|
||||
* [Make a System that Communicates](/design-engineering/make-it-communicate)
|
||||
* [Coding](/coding)
|
||||
* [Autonomous Parking](/coding/autonomous-parking)
|
||||
* [Object Detection](/coding/object-detection)
|
||||
* [Line Detection](/coding/line-detection)
|
||||
* [Maker](/maker)
|
||||
* [Make A Sound Machine](/maker/sound-machine)
|
||||
* [Make A Security Gadget](/maker/security-gadget)
|
||||
* [Tutorial Videos](/videos)
|
||||
* [undefined](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=5d009e5f93fbf479c2e5ed2bf87a7990&source=embed&photo%5fid=35719444)
|
||||
* [undefined](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=2008a566f1fb034d58d5ebe19ba8621f&source=embed&photo%5fid=35719467)
|
||||
* [undefined](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=629730c938e452f0fd7653fbc4708166&source=embed&photo%5fid=35719470)
|
||||
* [undefined](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=3513a83b87fe536b2dc512237465fd1b&source=embed&photo%5fid=35719471)
|
||||
* [undefined](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=5c594c2373367f7870196f519f3bfc7a&source=embed&photo%5fid=35719472)
|
||||
@@ -1,18 +0,0 @@
|
||||
# exit Program
|
||||
|
||||
Stops the program and returns to the brick menu
|
||||
|
||||
```sig
|
||||
brick.exitProgram();
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
Do a sequence of motor commands and stop the program.
|
||||
|
||||
```blocks
|
||||
motors.largeA.run(50)
|
||||
pause(500)
|
||||
motors.stopAll()
|
||||
brick.exitProgram();
|
||||
```
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"appref": "v1.2"
|
||||
}
|
||||
BIN
docs/static/getting-started/try-in-file-manager.png
vendored
BIN
docs/static/getting-started/try-in-file-manager.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 89 KiB |
6
docs/static/testfilelogo.svg
vendored
6
docs/static/testfilelogo.svg
vendored
@@ -1,6 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="svg4487" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.4" clip-rule="evenodd" version="1.1" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path id="path4485" fill="#696969" d="M16.1 2.7a13.8 13.8 0 00-4.4 27c.7 0 1-.4 1-.7v-2.4c-3.9.9-4.7-1.8-4.7-1.8-.6-1.6-1.5-2-1.5-2-1.3-1 0-.9 0-.9 1.4.1 2.2 1.4 2.2 1.4 1.2 2.1 3.2 1.5 4 1.2a3 3 0 01.9-1.9c-3.1-.3-6.3-1.5-6.3-6.8 0-1.5.5-2.7 1.4-3.7a5 5 0 01.1-3.7s1.2-.3 3.8 1.4a13.2 13.2 0 013.5-.4c1.2 0 2.4.1 3.5.4 2.6-1.7 3.8-1.4 3.8-1.4a5 5 0 01.1 3.7c.9 1 1.4 2.2 1.4 3.7 0 5.3-3.2 6.5-6.3 6.8.5.5 1 1.3 1 2.6V29c0 .4.2.8.9.6a13.8 13.8 0 00-4.4-27"/>
|
||||
<g id="text4497" fill="#000" fill-opacity="1" stroke="none" stroke-width=".7" aria-label="v" font-family="consolas" font-size="26.6" font-stretch="normal" font-style="normal" font-variant="normal" font-weight="400" letter-spacing="0" style="line-height:1.25;-inkscape-font-specification:consolas" transform="rotate(14.1)" word-spacing="0">
|
||||
<path id="path4499" stroke-width=".7" d="M21.4-1.7l2.9 8 3-8.3.8-1.5q.4-.4 1-.4.8 0 1.2.5.5.4.5 1v.6l-.3.5-.2.7-3.4 8.4-.4 1-.5 1-.7.5q-.4.2-1 .2-.8 0-1.2-.3-.5-.3-.7-.8l-.7-1.6-3.4-8.3q0-.4-.2-.7l-.2-.6-.1-.6.2-.7.6-.6q.4-.2.9-.2.9 0 1.2.5l.7 1.7z" font-family="Arial Rounded MT Bold" font-stretch="normal" font-style="normal" font-variant="normal" font-weight="400" style="-inkscape-font-specification:'Arial Rounded MT Bold, '"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,18 +1,16 @@
|
||||
# Troubleshooting
|
||||
|
||||
## Download issues
|
||||
# Troubleshooting download problems
|
||||
|
||||
If you're having trouble getting your code onto the EV3 Brick, try these steps to see if you can fix the problem.
|
||||
|
||||
### Check your **@drivename@** firmware
|
||||
## Check your **@drivename@** firmware
|
||||
|
||||
MakeCode needs a firmware version of **1.10E** or higher installed on your brick.
|
||||
|
||||
#### ~hint
|
||||
### ~hint
|
||||
|
||||
Firmware is the software that runs all the basic operations on your EV3 Brick. Your programs and the firmware work together to make the EV3 Brick do all things you want it to. Your EV3 Brick comes with firmware pre-installed, but it may need to be updated to work properly with MakeCode.
|
||||
|
||||
#### ~
|
||||
### ~
|
||||
|
||||
To check the the firmware version on your EV3 Brick:
|
||||
|
||||
@@ -27,15 +25,15 @@ To check the the firmware version on your EV3 Brick:
|
||||
|
||||
If you can't find the **Brick Info** or you see that the version is less than **1.10E**, **you need to upgrade your firmware**.
|
||||
|
||||
### Upgrade your **@drivename@**
|
||||
## Upgrade your **@drivename@**
|
||||
|
||||
If your a firmware version level is less than **1.10E**, you need to install an upgraded version. You can upgrade the firmware with the **EV3 Lab** or **EV3 Programming** software. Also, you can do a manual upgrade by downloading the firmware install file. See the [Firmware Update](https://education.lego.com/en-us/support/mindstorms-ev3/firmware-update) support page to learn about the upgrade process.
|
||||
|
||||
#### ~ hint
|
||||
### ~ hint
|
||||
|
||||
**Recommended:** Upgrade with the **[EV3 Device Manager](https://ev3manager.education.lego.com/)**
|
||||
|
||||
#### ~
|
||||
### ~
|
||||
|
||||
## Can I see the **@drivename@** drive on my computer?
|
||||
|
||||
@@ -47,24 +45,14 @@ On Windows, it looks like this in Explorer:
|
||||
|
||||
If you don't see the **@drivename@** drive, make sure your brick is powered on and check that your USB connection is good.
|
||||
|
||||
### The display on the EV3 Brick is blank
|
||||
## The display on the EV3 Brick is blank
|
||||
|
||||
Make sure your EV3 Brick is charged and powered on. If your it doesn't turn on, find the charger and plug it into wall power, then connect it to your EV3 Brick. Does it turn on and start up?
|
||||
|
||||
### I still can't see my @drivename@ drive
|
||||
## I still can't see my @drivename@ drive
|
||||
|
||||
Make sure that one end of your USB cable is firmly inserted into a USB port on the computer and the other end is connected to the EV3 Brick. If you still can't see the **@drivename@** drive, try a different port on the computer. If that doesn't work then maybe your cable is faulty or you need to reset the EV3 Brick.
|
||||
|
||||
## Why can't I delete my program (*.uf2) files from the Brick? #deletefiles
|
||||
|
||||
There's a bug in the firmware which prevents you from deleting the programs (``*.uf2`` files) from your EV3 Brick. There isn't a firmware update to fix this yet.
|
||||
|
||||
We have prepared a special program that lets you delete UF2 files from the brick.
|
||||
Download [these PDF instructions](/file-manager.pdf) and drop the PDF on the brick drive.
|
||||
This will present you with an menu for deleting files.
|
||||
|
||||
For other common questions, try the FAQ page https://makecode.mindstorms.com/faq.
|
||||
|
||||
## How do I reset my EV3 Brick?
|
||||
|
||||
If you think your USB connection is good and you still can't see your **@drivename@** drive, try giving the EV3 Brick a reset. You can follow these steps to reset:
|
||||
|
||||
@@ -3,15 +3,20 @@
|
||||
|
||||
import UF2 = pxtc.UF2;
|
||||
import { Ev3Wrapper } from "./wrap";
|
||||
import { bluetoothTryAgainAsync } from "./dialogs";
|
||||
|
||||
export let ev3: Ev3Wrapper;
|
||||
let confirmAsync: (options: any) => Promise<number>;
|
||||
|
||||
export function setConfirmAsync(cf: (options: any) => Promise<number>) {
|
||||
confirmAsync = cf;
|
||||
}
|
||||
|
||||
export function debug() {
|
||||
return initHidAsync()
|
||||
.then(w => w.downloadFileAsync("/tmp/dmesg.txt", v => console.log(pxt.Util.uint8ArrayToString(v))))
|
||||
}
|
||||
|
||||
|
||||
// Web Serial API https://wicg.github.io/serial/
|
||||
// chromium bug https://bugs.chromium.org/p/chromium/issues/detail?id=884928
|
||||
// Under experimental features in Chrome Desktop 77+
|
||||
@@ -162,7 +167,7 @@ export function initAsync(): Promise<void> {
|
||||
useHID = false
|
||||
} else {
|
||||
const nodehid = /nodehid/i.test(window.location.href);
|
||||
if (pxt.BrowserUtils.isLocalHost() && pxt.Cloud.localToken && nodehid)
|
||||
if (pxt.Cloud.isLocalHost() && pxt.Cloud.localToken && nodehid)
|
||||
useHID = true;
|
||||
}
|
||||
|
||||
@@ -278,9 +283,22 @@ export function deployCoreAsync(resp: pxtc.CompileResult) {
|
||||
return w.reconnectAsync(false)
|
||||
.catch(e => {
|
||||
// user easily forgets to stop robot
|
||||
bluetoothTryAgainAsync().then(() => w.disconnectAsync())
|
||||
.then(() => Promise.delay(1000))
|
||||
.then(() => w.reconnectAsync());
|
||||
if (confirmAsync)
|
||||
return confirmAsync({
|
||||
header: lf("Bluetooth download failed..."),
|
||||
htmlBody:
|
||||
`<ul>
|
||||
<li>${lf("Make sure to stop your program or exit portview on the EV3.")}</li>
|
||||
<li>${lf("Check your battery level.")}</li>
|
||||
<li>${lf("Close EV3 LabView or other MakeCode editor tabs.")}
|
||||
</ul>`,
|
||||
hasCloseIcon: true,
|
||||
hideCancel: true,
|
||||
hideAgree: false,
|
||||
agreeLbl: lf("Try again"),
|
||||
}).then(() => w.disconnectAsync())
|
||||
.then(() => Promise.delay(1000))
|
||||
.then(() => w.reconnectAsync());
|
||||
|
||||
// nothing we can do
|
||||
return Promise.reject(e);
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { canUseWebSerial, enableWebSerialAsync } from "./deploy";
|
||||
import { projectView } from "./extension";
|
||||
|
||||
let confirmAsync: (options: any) => Promise<number>;
|
||||
|
||||
export function bluetoothTryAgainAsync(): Promise<void> {
|
||||
return confirmAsync({
|
||||
header: lf("Bluetooth download failed..."),
|
||||
jsx: <ul>
|
||||
<li>{lf("Make sure to stop your program or exit portview on the EV3.")}</li>
|
||||
<li>{lf("Check your battery level.")}</li>
|
||||
<li>{lf("Close EV3 LabView or other MakeCode editor tabs.")}</li>
|
||||
</ul>,
|
||||
hasCloseIcon: false,
|
||||
hideCancel: true,
|
||||
hideAgree: false,
|
||||
agreeLbl: lf("Try again")
|
||||
}).then(r => {});
|
||||
}
|
||||
|
||||
function enableWebSerialAndCompileAsync() {
|
||||
return enableWebSerialAsync()
|
||||
.then(() => Promise.delay(500))
|
||||
.then(() => projectView.compile());
|
||||
}
|
||||
|
||||
let bluetoothDialogShown = false;
|
||||
function explainWebSerialPairingAsync(): Promise<void> {
|
||||
if (!confirmAsync || bluetoothDialogShown) return Promise.resolve();
|
||||
|
||||
bluetoothDialogShown = true;
|
||||
return confirmAsync({
|
||||
header: lf("Bluetooth pairing"),
|
||||
hasCloseIcon: false,
|
||||
hideCancel: true,
|
||||
buttons: [{
|
||||
label: lf("Help"),
|
||||
icon: "question circle",
|
||||
className: "lightgrey",
|
||||
url: "/bluetooth"
|
||||
}],
|
||||
jsx: <p>
|
||||
{lf("You will be prompted to select a serial port.")}
|
||||
{pxt.BrowserUtils.isWindows()
|
||||
? lf("Look for 'Standard Serial over Bluetooth link'.")
|
||||
: lf("Loop for 'cu.EV3-SerialPort'.")}
|
||||
{lf("If you have paired multiple EV3, you might have to try out multiple ports until you find the correct one.")}
|
||||
</p>
|
||||
}).then(() => { })
|
||||
}
|
||||
|
||||
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.
|
||||
// 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 jsx =
|
||||
<div className="ui grid stackable">
|
||||
<div className="column five wide" style={{ backgroundColor: "#E2E2E2" }}>
|
||||
<div className="ui header">{lf("First time here?")}</div>
|
||||
<strong style={{ fontSize: "small" }}>{lf("You must have version 1.10E or above of the firmware")}</strong>
|
||||
<div style={{ justifyContent: "center", display: "flex", padding: "1rem" }}>
|
||||
<img className="ui image" src="/static/download/firmware.png" style={{ height: "100px" }} />
|
||||
</div>
|
||||
<a href="/troubleshoot" target="_blank">{lf("Check your firmware version here and update if needed")}</a>
|
||||
</div>
|
||||
<div className="column eleven wide">
|
||||
<div className="ui grid">
|
||||
<div className="row">
|
||||
<div className="column">
|
||||
<div className="ui two column grid padded">
|
||||
<div className="column">
|
||||
<div className="ui">
|
||||
<div className="image">
|
||||
<img className="ui medium rounded image" src="/static/download/connect.svg" style={{ height: "109px", width: "261px", marginBottom: "1rem" }} />
|
||||
</div>
|
||||
<div className="content">
|
||||
<div className="description">
|
||||
<span className="ui yellow circular label">1</span>
|
||||
<strong>{lf("Connect the EV3 to your computer with a USB cable")}</strong>
|
||||
<br />
|
||||
<span style={{ fontSize: "small" }}>{lf("Use the miniUSB port on the top of the EV3 Brick")}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="column">
|
||||
<div className="ui">
|
||||
<div className="image">
|
||||
<img className="ui medium rounded image" src="/static/download/transfer.svg" style={{ height: "109px", width: "261px", marginBottom: "1rem" }} />
|
||||
</div>
|
||||
<div className="content">
|
||||
<div className="description">
|
||||
<span className="ui yellow circular label">2</span>
|
||||
<strong>{lf("Move the .uf2 file to the EV3 Brick")}</strong>
|
||||
<br />
|
||||
<span style={{ fontSize: "small" }}>{lf("Locate the downloaded .uf2 file and drag it to the EV3 USB drive")}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>;
|
||||
|
||||
return confirmAsync({
|
||||
header: lf("Download to your EV3"),
|
||||
jsx,
|
||||
hasCloseIcon: true,
|
||||
hideCancel: true,
|
||||
hideAgree: false,
|
||||
agreeLbl: lf("I got it"),
|
||||
className: 'downloaddialog',
|
||||
buttons: [canUseWebSerial() ? {
|
||||
label: lf("Bluetooth"),
|
||||
icon: "bluetooth",
|
||||
className: "bluetooth focused",
|
||||
onclick: () => {
|
||||
pxt.tickEvent("bluetooth.enable");
|
||||
explainWebSerialPairingAsync()
|
||||
.then(() => enableWebSerialAndCompileAsync())
|
||||
.done();
|
||||
}
|
||||
} : undefined, downloadAgain ? {
|
||||
label: fn,
|
||||
icon: "download",
|
||||
className: "lightgrey focused",
|
||||
url,
|
||||
fileName: fn
|
||||
} : undefined, docUrl ? {
|
||||
label: lf("Help"),
|
||||
icon: "help",
|
||||
className: "lightgrey",
|
||||
url: docUrl
|
||||
} : undefined]
|
||||
//timeout: 20000
|
||||
}).then(() => { });
|
||||
}
|
||||
@@ -1,26 +1,144 @@
|
||||
/// <reference path="../node_modules/pxt-core/localtypings/pxtarget.d.ts" />
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtblocks.d.ts" />
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtcompiler.d.ts" />
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtlib.d.ts" />
|
||||
/// <reference path="../node_modules/pxt-core/built/pxteditor.d.ts"/>
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
|
||||
|
||||
import { deployCoreAsync, initAsync } from "./deploy";
|
||||
import { showUploadDialogAsync } from "./dialogs";
|
||||
|
||||
export let projectView: pxt.editor.IProjectView;
|
||||
import { deployCoreAsync, initAsync, canUseWebSerial, enableWebSerialAsync, setConfirmAsync } from "./deploy";
|
||||
|
||||
let bluetoothDialogShown = false;
|
||||
pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): Promise<pxt.editor.ExtensionResult> {
|
||||
const projectView = opts.projectView;
|
||||
pxt.debug('loading pxt-ev3 target extensions...')
|
||||
projectView = opts.projectView;
|
||||
|
||||
function enableWebSerialAndCompileAsync() {
|
||||
return enableWebSerialAsync()
|
||||
.then(() => Promise.delay(500))
|
||||
.then(() => projectView.compile());
|
||||
}
|
||||
|
||||
const res: pxt.editor.ExtensionResult = {
|
||||
deployAsync: deployCoreAsync,
|
||||
showUploadInstructionsAsync: showUploadDialogAsync
|
||||
};
|
||||
deployCoreAsync,
|
||||
showUploadInstructionsAsync: (fn: string, url: string, confirmAsync: (options: any) => Promise<number>) => {
|
||||
setConfirmAsync(confirmAsync);
|
||||
// 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 htmlBody = `
|
||||
<div class="ui grid stackable">
|
||||
<div class="column five wide" style="background-color: #E2E2E2;">
|
||||
<div class="ui header">${lf("First time here?")}</div>
|
||||
<strong style="font-size:small">${lf("You must have version 1.10E or above of the firmware")}</strong>
|
||||
<div style="justify-content: center;display: flex;padding: 1rem;">
|
||||
<img class="ui image" src="/static/download/firmware.png" style="height:100px;" />
|
||||
</div>
|
||||
<a href="/troubleshoot" target="_blank">${lf("Check your firmware version here and update if needed")}</a>
|
||||
</div>
|
||||
<div class="column eleven wide">
|
||||
<div class="ui grid">
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
<div class="ui two column grid padded">
|
||||
<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 the EV3 to your computer with a USB cable")}</strong>
|
||||
<br />
|
||||
<span style="font-size:small">${lf("Use the miniUSB port on the top of the EV3 Brick")}</span>
|
||||
</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 yellow circular label">2</span>
|
||||
<strong>${lf("Move the .uf2 file to the EV3 Brick")}</strong>
|
||||
<br />
|
||||
<span style="font-size:small">${lf("Locate the downloaded .uf2 file and drag it to the EV3 USB drive")}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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"),
|
||||
className: 'downloaddialog',
|
||||
buttons: [canUseWebSerial() ? {
|
||||
label: lf("Bluetooth"),
|
||||
icon: "bluetooth",
|
||||
className: "bluetooth focused",
|
||||
onclick: () => {
|
||||
pxt.tickEvent("bluetooth.enable");
|
||||
if (bluetoothDialogShown) {
|
||||
enableWebSerialAndCompileAsync().done();
|
||||
} else {
|
||||
bluetoothDialogShown = true;
|
||||
confirmAsync({
|
||||
header: lf("Bluetooth pairing"),
|
||||
hasCloseIcon: true,
|
||||
hideCancel: true,
|
||||
buttons: [{
|
||||
label: lf("Help"),
|
||||
icon: "question circle",
|
||||
className: "lightgrey",
|
||||
url: "/bluetooth"
|
||||
}],
|
||||
htmlBody: `<p>
|
||||
${lf("You will be prompted to select a serial port.")}
|
||||
${pxt.BrowserUtils.isWindows()
|
||||
? lf("Look for 'Standard Serial over Bluetooth link'.")
|
||||
: lf("Loop for 'cu.EV3-SerialPort'.")}
|
||||
${lf("If you have paired multiple EV3, you might have to try out multiple ports until you find the correct one.")}
|
||||
</p>
|
||||
`
|
||||
}).then(() => enableWebSerialAndCompileAsync())
|
||||
}
|
||||
}
|
||||
} : undefined, downloadAgain ? {
|
||||
label: fn,
|
||||
icon: "download",
|
||||
className: "lightgrey focused",
|
||||
url,
|
||||
fileName: fn
|
||||
} : undefined, docUrl ? {
|
||||
label: lf("Help"),
|
||||
icon: "help",
|
||||
className: "lightgrey",
|
||||
url: docUrl
|
||||
} : undefined]
|
||||
//timeout: 20000
|
||||
}).then(() => { });
|
||||
}
|
||||
};
|
||||
initAsync().catch(e => {
|
||||
// probably no HID - we'll try this again upon deployment
|
||||
})
|
||||
return Promise.resolve<pxt.editor.ExtensionResult>(res);
|
||||
}
|
||||
|
||||
// When require()d from node, bind the global pxt namespace
|
||||
// namespace pxt {
|
||||
// export const dummyExport = 1;
|
||||
// }
|
||||
// eval("if (typeof process === 'object' && process + '' === '[object process]') pxt = global.pxt")
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitAny": false,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"declaration": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"isolatedModules": false,
|
||||
"outDir": "../built/editor",
|
||||
"rootDir": ".",
|
||||
"newLine": "LF",
|
||||
"sourceMap": false,
|
||||
"jsx": "react"
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"declaration": true
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
import { FieldPorts } from "./field_ports";
|
||||
import { FieldMotors } from "./field_motors";
|
||||
import { FieldSpeed } from "./field_speed";
|
||||
import { FieldBrickButtons } from "./field_brickbuttons";
|
||||
import { FieldTurnRatio } from "./field_turnratio";
|
||||
import { FieldColorEnum } from "./field_color";
|
||||
import { FieldMusic } from "./field_music";
|
||||
|
||||
@@ -17,9 +19,15 @@ pxt.editor.initFieldExtensionsAsync = function (opts: pxt.editor.FieldExtensionO
|
||||
}, {
|
||||
selector: "motors",
|
||||
editor: FieldMotors
|
||||
}, {
|
||||
selector: "speed",
|
||||
editor: FieldSpeed
|
||||
}, {
|
||||
selector: "brickbuttons",
|
||||
editor: FieldBrickButtons
|
||||
}, {
|
||||
selector: "turnratio",
|
||||
editor: FieldTurnRatio
|
||||
}, {
|
||||
selector: "colorenum",
|
||||
editor: FieldColorEnum
|
||||
|
||||
@@ -121,17 +121,17 @@ export class FieldBrickButtons extends Blockly.FieldDropdown implements Blockly.
|
||||
Blockly.DropDownDiv.setColour('#ffffff', '#dddddd');
|
||||
|
||||
// Calculate positioning based on the field position.
|
||||
let scale = (<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).scale;
|
||||
let bBox = { width: this.size_.width, height: this.size_.height };
|
||||
var scale = this.sourceBlock_.workspace.scale;
|
||||
var bBox = { width: this.size_.width, height: this.size_.height };
|
||||
bBox.width *= scale;
|
||||
bBox.height *= scale;
|
||||
let position = this.fieldGroup_.getBoundingClientRect();
|
||||
let primaryX = position.left + bBox.width / 2;
|
||||
let primaryY = position.top + bBox.height;
|
||||
let secondaryX = primaryX;
|
||||
let secondaryY = position.top;
|
||||
var position = this.fieldGroup_.getBoundingClientRect();
|
||||
var primaryX = position.left + bBox.width / 2;
|
||||
var primaryY = position.top + bBox.height;
|
||||
var secondaryX = primaryX;
|
||||
var secondaryY = position.top;
|
||||
// Set bounds to workspace; show the drop-down.
|
||||
(Blockly.DropDownDiv as any).setBoundsElement((<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).getParentSvg().parentNode);
|
||||
(Blockly.DropDownDiv as any).setBoundsElement(this.sourceBlock_.workspace.getParentSvg().parentNode);
|
||||
(Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY,
|
||||
this.onHide_.bind(this));
|
||||
}
|
||||
@@ -152,10 +152,9 @@ export class FieldBrickButtons extends Blockly.FieldDropdown implements Blockly.
|
||||
* Callback for when the drop-down is hidden.
|
||||
*/
|
||||
private onHide_ = function () {
|
||||
const content = Blockly.DropDownDiv.getContentDiv();
|
||||
content.removeAttribute('role');
|
||||
content.removeAttribute('aria-haspopup');
|
||||
content.removeAttribute('aria-activedescendant');
|
||||
(content as HTMLElement).style.width = '';
|
||||
Blockly.DropDownDiv.content_.removeAttribute('role');
|
||||
Blockly.DropDownDiv.content_.removeAttribute('aria-haspopup');
|
||||
Blockly.DropDownDiv.content_.removeAttribute('aria-activedescendant');
|
||||
Blockly.DropDownDiv.getContentDiv().style.width = '';
|
||||
};
|
||||
}
|
||||
@@ -44,7 +44,7 @@ export class FieldColorEnum extends pxtblockly.FieldColorNumber implements Block
|
||||
* @return {string} Current colour in '#rrggbb' format.
|
||||
*/
|
||||
getValue(opt_asHex?: boolean) {
|
||||
const colour = this.mapColour(this.value_);
|
||||
var colour = this.mapColour(this.colour_);
|
||||
if (!opt_asHex && colour.indexOf('#') > -1) {
|
||||
return `0x${colour.replace(/^#/, '')}`;
|
||||
}
|
||||
@@ -56,13 +56,13 @@ export class FieldColorEnum extends pxtblockly.FieldColorNumber implements Block
|
||||
* @param {string} colour The new colour in '#rrggbb' format.
|
||||
*/
|
||||
setValue(colorStr: string) {
|
||||
let colour = this.mapEnum(colorStr);
|
||||
var colour = this.mapEnum(colorStr);
|
||||
if (this.sourceBlock_ && Blockly.Events.isEnabled() &&
|
||||
this.value_ != colour) {
|
||||
this.colour_ != colour) {
|
||||
Blockly.Events.fire(new (Blockly as any).Events.BlockChange(
|
||||
this.sourceBlock_, 'field', this.name, this.value_, colour));
|
||||
this.sourceBlock_, 'field', this.name, this.colour_, colour));
|
||||
}
|
||||
this.value_ = colour;
|
||||
this.colour_ = colour;
|
||||
if (this.sourceBlock_) {
|
||||
this.sourceBlock_.setColour(colour, colour, colour);
|
||||
}
|
||||
|
||||
@@ -46,31 +46,31 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
(this as any).arrowX_ = 0;
|
||||
/** @type {Number} */
|
||||
this.arrowY_ = 11;
|
||||
this.arrow_ = Blockly.utils.dom.createSvgElement('image', {
|
||||
this.arrow_ = Blockly.utils.createSvgElement('image', {
|
||||
'height': (this as any).arrowSize_ + 'px',
|
||||
'width': (this as any).arrowSize_ + 'px'
|
||||
}, null);
|
||||
});
|
||||
this.arrow_.setAttributeNS('http://www.w3.org/1999/xlink',
|
||||
'xlink:href', (Blockly.FieldDropdown as any).DROPDOWN_SVG_DATAURI);
|
||||
|
||||
this.arrow2_ = <SVGImageElement>Blockly.utils.dom.createSvgElement('image', {
|
||||
this.arrow2_ = Blockly.utils.createSvgElement('image', {
|
||||
'height': (this as any).arrowSize_ + 'px',
|
||||
'width': (this as any).arrowSize_ + 'px'
|
||||
}, null);
|
||||
});
|
||||
this.arrow2_.setAttributeNS('http://www.w3.org/1999/xlink',
|
||||
'xlink:href', (Blockly.FieldDropdown as any).DROPDOWN_SVG_DATAURI);
|
||||
(this as any).className_ += ' blocklyDropdownText';
|
||||
|
||||
// Build the DOM.
|
||||
this.fieldGroup_ = Blockly.utils.dom.createSvgElement('g', {}, null);
|
||||
this.fieldGroup_ = Blockly.utils.createSvgElement('g', {}, null);
|
||||
if (!this.visible_) {
|
||||
(this.fieldGroup_ as any).style.display = 'none';
|
||||
}
|
||||
// Adjust X to be flipped for RTL. Position is relative to horizontal start of source block.
|
||||
let size = this.getSize();
|
||||
let fieldX = (this.sourceBlock_.RTL) ? -size.width / 2 : size.width / 2;
|
||||
var size = this.getSize();
|
||||
var fieldX = (this.sourceBlock_.RTL) ? -size.width / 2 : size.width / 2;
|
||||
/** @type {!Element} */
|
||||
this.textElement_ = Blockly.utils.dom.createSvgElement('text',
|
||||
this.textElement_ = Blockly.utils.createSvgElement('text',
|
||||
{
|
||||
'class': (this as any).className_,
|
||||
'x': fieldX,
|
||||
@@ -79,7 +79,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
},
|
||||
this.fieldGroup_);
|
||||
fieldX += 10; // size of first group.
|
||||
this.textElement2_ = <SVGTextElement>Blockly.utils.dom.createSvgElement('text',
|
||||
this.textElement2_ = Blockly.utils.createSvgElement('text',
|
||||
{
|
||||
'class': (this as any).className_,
|
||||
'x': fieldX,
|
||||
@@ -89,17 +89,17 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
this.fieldGroup_);
|
||||
|
||||
this.updateEditable();
|
||||
(this.sourceBlock_ as Blockly.BlockSvg).getSvgRoot().appendChild(this.fieldGroup_);
|
||||
this.sourceBlock_.getSvgRoot().appendChild(this.fieldGroup_);
|
||||
// Force a render.
|
||||
this.render_();
|
||||
this.isDirty_ = true;
|
||||
this.size_.width = 0;
|
||||
(this as any).mouseDownWrapper_ =
|
||||
Blockly.bindEventWithChecks_((this as any).getClickTarget_(), 'mousedown', this,
|
||||
(this as any).onMouseDown_);
|
||||
|
||||
// Add second dropdown
|
||||
if (this.shouldShowRect_()) {
|
||||
this.box_ = <SVGRectElement>Blockly.utils.dom.createSvgElement('rect', {
|
||||
this.box_ = Blockly.utils.createSvgElement('rect', {
|
||||
'rx': (Blockly.BlockSvg as any).CORNER_RADIUS,
|
||||
'ry': (Blockly.BlockSvg as any).CORNER_RADIUS,
|
||||
'x': 0,
|
||||
@@ -112,7 +112,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
'fill-opacity': 1
|
||||
}, null);
|
||||
this.fieldGroup_.insertBefore(this.box_, this.textElement_);
|
||||
this.box2_ = <SVGRectElement>Blockly.utils.dom.createSvgElement('rect', {
|
||||
this.box2_ = Blockly.utils.createSvgElement('rect', {
|
||||
'rx': (Blockly.BlockSvg as any).CORNER_RADIUS,
|
||||
'ry': (Blockly.BlockSvg as any).CORNER_RADIUS,
|
||||
'x': 0,
|
||||
@@ -128,7 +128,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
}
|
||||
|
||||
// Force a reset of the text to add the arrow.
|
||||
let text = this.text_;
|
||||
var text = this.text_;
|
||||
this.text_ = null;
|
||||
this.setText(text);
|
||||
}
|
||||
@@ -149,9 +149,9 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
getFirstValueI11n(value: string) {
|
||||
const firstValue = this.getFirstValue(value);
|
||||
const motorOptions = {
|
||||
'medium motor': lf("medium motor"),
|
||||
'large motor': lf("large motor"),
|
||||
'large motors': lf("large motors")
|
||||
'medium motor': lf('medium motor'),
|
||||
'large motor': lf('large motor'),
|
||||
'large motors': lf('large motors')
|
||||
}
|
||||
return motorOptions[firstValue];
|
||||
}
|
||||
@@ -179,7 +179,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
// Not rendered yet.
|
||||
return;
|
||||
}
|
||||
let text = this.text_;
|
||||
var text = this.text_;
|
||||
if (text.length > this.maxDisplayLength) {
|
||||
// Truncate displayed string and add an ellipsis ('...').
|
||||
text = text.substring(0, this.maxDisplayLength - 2) + '\u2026';
|
||||
@@ -200,11 +200,11 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
// Prevent the field from disappearing if empty.
|
||||
text = Blockly.Field.NBSP;
|
||||
}
|
||||
let textNode = document.createTextNode(text);
|
||||
var textNode = document.createTextNode(text);
|
||||
this.textElement2_.appendChild(textNode);
|
||||
|
||||
// Cached width is obsolete. Clear it.
|
||||
this.isDirty_ = true;
|
||||
this.size_.width = 0;
|
||||
};
|
||||
|
||||
patchDualMotorText(text: string) {
|
||||
@@ -233,8 +233,8 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
if (this.textElement2_) {
|
||||
this.textElement2_.parentNode.appendChild(this.arrow2_);
|
||||
}
|
||||
if (this.sourceBlock_ && (<Blockly.BlockSvg>this.sourceBlock_).rendered) {
|
||||
(<Blockly.BlockSvg>this.sourceBlock_).render();
|
||||
if (this.sourceBlock_ && this.sourceBlock_.rendered) {
|
||||
this.sourceBlock_.render();
|
||||
this.sourceBlock_.bumpNeighbours_();
|
||||
}
|
||||
}
|
||||
@@ -244,7 +244,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
return 0;
|
||||
}
|
||||
|
||||
let addedWidth = 0;
|
||||
var addedWidth = 0;
|
||||
if (this.sourceBlock_.RTL) {
|
||||
(this as any).arrow2X_ = (this as any).arrowSize_ - (Blockly.BlockSvg as any).DROPDOWN_ARROW_PADDING;
|
||||
addedWidth = (this as any).arrowSize_ + (Blockly.BlockSvg as any).DROPDOWN_ARROW_PADDING;
|
||||
@@ -263,10 +263,10 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
return addedWidth;
|
||||
};
|
||||
|
||||
updateSize_() {
|
||||
updateWidth() {
|
||||
// Calculate width of field
|
||||
let width = Blockly.Field.getCachedWidth(this.textElement_);
|
||||
let width2 = Blockly.Field.getCachedWidth(this.textElement2_);
|
||||
var width = Blockly.Field.getCachedWidth(this.textElement_);
|
||||
var width2 = Blockly.Field.getCachedWidth(this.textElement2_);
|
||||
|
||||
// Add padding to left and right of text.
|
||||
if (this.EDITABLE) {
|
||||
@@ -311,15 +311,15 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
|
||||
// First dropdown
|
||||
// Use one of the following options, medium motor, large motor or large motors (translated)
|
||||
const textNode1 = document.createTextNode(this.getFirstValueI11n(<string>this.value_));
|
||||
const textNode1 = document.createTextNode(this.getFirstValueI11n(this.value_));
|
||||
this.textElement_.appendChild(textNode1);
|
||||
|
||||
// Second dropdown, no need to translate. Only port numbers
|
||||
if (this.textElement2_) {
|
||||
const textNode2 = document.createTextNode(this.getSecondValue(<string>this.value_));
|
||||
const textNode2 = document.createTextNode(this.getSecondValue(this.value_));
|
||||
this.textElement2_.appendChild(textNode2);
|
||||
}
|
||||
this.updateSize_();
|
||||
this.updateWidth();
|
||||
|
||||
// Update text centering, based on newly calculated width.
|
||||
let centerTextX = ((this as any).width1 - this.arrowWidth_) / 2;
|
||||
@@ -347,8 +347,8 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
}
|
||||
|
||||
// Apply new text element x position.
|
||||
let width = Blockly.Field.getCachedWidth(this.textElement_);
|
||||
let newX = centerTextX - width / 2;
|
||||
var width = Blockly.Field.getCachedWidth(this.textElement_);
|
||||
var newX = centerTextX - width / 2;
|
||||
this.textElement_.setAttribute('x', `${newX}`);
|
||||
|
||||
// Update text centering, based on newly calculated width.
|
||||
@@ -377,8 +377,8 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
}
|
||||
|
||||
// Apply new text element x position.
|
||||
let width2 = Blockly.Field.getCachedWidth(this.textElement2_);
|
||||
let newX2 = centerTextX2 - width2 / 2;
|
||||
var width2 = Blockly.Field.getCachedWidth(this.textElement2_);
|
||||
var newX2 = centerTextX2 - width2 / 2;
|
||||
this.textElement2_.setAttribute('x', `${newX2 + (this as any).width1 + Blockly.BlockSvg.BOX_FIELD_PADDING}`);
|
||||
}
|
||||
|
||||
@@ -401,7 +401,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
if (Blockly.DropDownDiv.hideIfOwner(this)) {
|
||||
return;
|
||||
}
|
||||
this.isFirst_ = e.clientX - this.getScaledBBox_().left < ((this as any).width1 * (<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).scale);
|
||||
this.isFirst_ = e.clientX - this.getScaledBBox_().left < ((this as any).width1 * this.sourceBlock_.workspace.scale);
|
||||
// If there is an existing drop-down someone else owns, hide it immediately and clear it.
|
||||
Blockly.DropDownDiv.hideWithoutAnimation();
|
||||
Blockly.DropDownDiv.clearContent();
|
||||
@@ -411,14 +411,14 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
// Accessibility properties
|
||||
contentDiv.setAttribute('role', 'menu');
|
||||
contentDiv.setAttribute('aria-haspopup', 'true');
|
||||
const foptions = this.getOptions(); // [img info, text]
|
||||
let options = this.getOptions();
|
||||
|
||||
let opts = {};
|
||||
let conts = {};
|
||||
let vals = {};
|
||||
// Go through all option values and split them into groups
|
||||
for (let opt = 0; opt < foptions.length; opt++) {
|
||||
const value = foptions[opt][1];
|
||||
for (let opt = 0; opt < options.length; opt++) {
|
||||
const value = options[opt][1];
|
||||
const motorValue = value.substring(value.indexOf('.') + 1);
|
||||
const typeValue = motorValue.indexOf('large') == 0 ? 'large' : 'medium';
|
||||
const portValue = motorValue.indexOf('large') == 0 ? motorValue.substring(5) : motorValue.substring(6);
|
||||
@@ -429,14 +429,13 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
if (!opts[key]) opts[key] = [];
|
||||
opts[key].push(portValue);
|
||||
|
||||
conts[text] = foptions[opt][0];
|
||||
conts[text] = options[opt][0];
|
||||
vals[text] = value;
|
||||
}
|
||||
|
||||
const currentFirst = this.getFirstValue(<string>this.value_);
|
||||
//const currentSecond = this.getSecondValue(<string>this.value_);
|
||||
const currentFirst = this.getFirstValue(this.value_);
|
||||
const currentSecond = this.getSecondValue(this.value_);
|
||||
|
||||
let options: string[];
|
||||
if (!this.isFirst_) {
|
||||
options = opts[currentFirst];
|
||||
} else {
|
||||
@@ -527,7 +526,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
Blockly.DropDownDiv.setColour(this.backgroundColour_, this.borderColour_);
|
||||
|
||||
// Calculate positioning based on the field position.
|
||||
let scale = (<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).scale;
|
||||
let scale = this.sourceBlock_.workspace.scale;
|
||||
let width = this.isFirst_ ? (this as any).width1 : (this as any).width2;
|
||||
let bBox = { width: this.size_.width, height: this.size_.height };
|
||||
width *= scale;
|
||||
@@ -539,7 +538,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
let secondaryX = primaryX;
|
||||
let secondaryY = position.top;
|
||||
// Set bounds to workspace; show the drop-down.
|
||||
(Blockly.DropDownDiv as any).setBoundsElement((<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).getParentSvg().parentNode);
|
||||
(Blockly.DropDownDiv as any).setBoundsElement(this.sourceBlock_.workspace.getParentSvg().parentNode);
|
||||
(Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY,
|
||||
this.onHide_.bind(this));
|
||||
|
||||
@@ -562,11 +561,10 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
|
||||
* Callback for when the drop-down is hidden.
|
||||
*/
|
||||
protected onHide_() {
|
||||
const content = Blockly.DropDownDiv.getContentDiv();
|
||||
content.removeAttribute('role');
|
||||
content.removeAttribute('aria-haspopup');
|
||||
content.removeAttribute('aria-activedescendant');
|
||||
(content as HTMLElement).style.width = '';
|
||||
Blockly.DropDownDiv.content_.removeAttribute('role');
|
||||
Blockly.DropDownDiv.content_.removeAttribute('aria-haspopup');
|
||||
Blockly.DropDownDiv.content_.removeAttribute('aria-activedescendant');
|
||||
Blockly.DropDownDiv.getContentDiv().style.width = '';
|
||||
if (this.isFirst_ && this.box_) {
|
||||
this.box_.setAttribute('fill', this.sourceBlock_.getColour());
|
||||
} else if (!this.isFirst_ && this.box2_) {
|
||||
|
||||
@@ -26,7 +26,7 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
this.width_ = parseInt(options.width) || 380;
|
||||
|
||||
this.setText = Blockly.FieldDropdown.prototype.setText;
|
||||
this.updateSize_ = (Blockly.Field as any).prototype.updateSize_;
|
||||
this.updateWidth = (Blockly.Field as any).prototype.updateWidth;
|
||||
this.updateTextNode_ = Blockly.Field.prototype.updateTextNode_;
|
||||
|
||||
if (!pxt.BrowserUtils.isIE() && !soundCache) {
|
||||
@@ -78,14 +78,14 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
contentDiv.style.width = (this as any).width_ + 'px';
|
||||
contentDiv.style.cssFloat = 'left';
|
||||
|
||||
(dropdownDiv as HTMLElement).style.maxHeight = `410px`;
|
||||
dropdownDiv.style.maxHeight = `410px`;
|
||||
dropdownDiv.appendChild(categoriesDiv);
|
||||
dropdownDiv.appendChild(contentDiv);
|
||||
|
||||
Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(), this.sourceBlock_.getColourTertiary());
|
||||
|
||||
// Calculate positioning based on the field position.
|
||||
let scale = (<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).scale;
|
||||
let scale = this.sourceBlock_.workspace.scale;
|
||||
let bBox = { width: this.size_.width, height: this.size_.height };
|
||||
bBox.width *= scale;
|
||||
bBox.height *= scale;
|
||||
@@ -95,7 +95,7 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
let secondaryX = primaryX;
|
||||
let secondaryY = position.top;
|
||||
// Set bounds to workspace; show the drop-down.
|
||||
(Blockly.DropDownDiv as any).setBoundsElement((<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).getParentSvg().parentNode);
|
||||
(Blockly.DropDownDiv as any).setBoundsElement(this.sourceBlock_.workspace.getParentSvg().parentNode);
|
||||
(Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY,
|
||||
this.onHide_.bind(this));
|
||||
|
||||
@@ -236,7 +236,7 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
|
||||
protected onHide_() {
|
||||
super.onHide_();
|
||||
(Blockly.DropDownDiv.getContentDiv() as HTMLElement).style.maxHeight = '';
|
||||
Blockly.DropDownDiv.getContentDiv().style.maxHeight = '';
|
||||
this.stopSounds();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export class FieldPorts extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
this.width_ = parseInt(options.width) || 300;
|
||||
|
||||
this.setText = Blockly.FieldDropdown.prototype.setText;
|
||||
this.updateSize_ = (Blockly.Field as any).prototype.updateSize_;
|
||||
this.updateWidth = (Blockly.Field as any).prototype.updateWidth;
|
||||
this.updateTextNode_ = Blockly.Field.prototype.updateTextNode_;
|
||||
}
|
||||
|
||||
|
||||
98
fieldeditors/field_speed.ts
Normal file
98
fieldeditors/field_speed.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
/// <reference path="../node_modules/pxt-core/localtypings/blockly.d.ts"/>
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
|
||||
|
||||
export interface FieldSpeedOptions extends Blockly.FieldCustomOptions {
|
||||
min?: string;
|
||||
max?: string;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
export class FieldSpeed extends Blockly.FieldSlider implements Blockly.FieldCustom {
|
||||
public isFieldCustom_ = true;
|
||||
|
||||
private params: any;
|
||||
|
||||
private speedSVG: SVGElement;
|
||||
private circleBar: SVGCircleElement;
|
||||
private reporter: SVGTextElement;
|
||||
|
||||
/**
|
||||
* Class for a color wheel field.
|
||||
* @param {number|string} value The initial content of the field.
|
||||
* @param {Function=} opt_validator An optional function that is called
|
||||
* to validate any constraints on what the user entered. Takes the new
|
||||
* text as an argument and returns either the accepted text, a replacement
|
||||
* text, or null to abort the change.
|
||||
* @extends {Blockly.FieldNumber}
|
||||
* @constructor
|
||||
*/
|
||||
constructor(value_: any, params: FieldSpeedOptions, opt_validator?: Function) {
|
||||
super(String(value_), '-100', '100', null, '10', 'Speed', opt_validator);
|
||||
this.params = params;
|
||||
if (this.params['min']) this.min_ = parseFloat(this.params.min);
|
||||
if (this.params['max']) this.max_ = parseFloat(this.params.max);
|
||||
if (this.params['label']) this.labelText_ = this.params.label;
|
||||
|
||||
(this as any).sliderColor_ = '#a8aaa8';
|
||||
}
|
||||
|
||||
createLabelDom_(labelText: string) {
|
||||
var labelContainer = document.createElement('div');
|
||||
this.speedSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg") as SVGGElement;
|
||||
pxsim.svg.hydrate(this.speedSVG, {
|
||||
viewBox: "0 0 200 100",
|
||||
width: "170"
|
||||
});
|
||||
|
||||
labelContainer.appendChild(this.speedSVG);
|
||||
|
||||
const outerCircle = pxsim.svg.child(this.speedSVG, "circle", {
|
||||
'stroke-dasharray': '565.48', 'stroke-dashoffset': '0',
|
||||
'cx': 100, 'cy': 100, 'r': '90', 'style': `fill:transparent; transition: stroke-dashoffset 0.1s linear;`,
|
||||
'stroke': '#a8aaa8', 'stroke-width': '1rem'
|
||||
}) as SVGCircleElement;
|
||||
this.circleBar = pxsim.svg.child(this.speedSVG, "circle", {
|
||||
'stroke-dasharray': '565.48', 'stroke-dashoffset': '0',
|
||||
'cx': 100, 'cy': 100, 'r': '90', 'style': `fill:transparent; transition: stroke-dashoffset 0.1s linear;`,
|
||||
'stroke': '#f12a21', 'stroke-width': '1rem'
|
||||
}) as SVGCircleElement;
|
||||
|
||||
this.reporter = pxsim.svg.child(this.speedSVG, "text", {
|
||||
'x': 100, 'y': 80,
|
||||
'text-anchor': 'middle', 'dominant-baseline': 'middle',
|
||||
'style': 'font-size: 50px',
|
||||
'class': 'sim-text inverted number'
|
||||
}) as SVGTextElement;
|
||||
|
||||
// labelContainer.setAttribute('class', 'blocklyFieldSliderLabel');
|
||||
var readout = document.createElement('span');
|
||||
readout.setAttribute('class', 'blocklyFieldSliderReadout');
|
||||
// var label = document.createElement('span');
|
||||
// label.setAttribute('class', 'blocklyFieldSliderLabelText');
|
||||
// label.innerHTML = labelText;
|
||||
// labelContainer.appendChild(label);
|
||||
// labelContainer.appendChild(readout);
|
||||
return [labelContainer, readout];
|
||||
};
|
||||
|
||||
setReadout_(readout: Element, value: string) {
|
||||
let x = parseFloat(value) || 0;
|
||||
this.updateSpeed(x);
|
||||
// Update reporter
|
||||
this.reporter.textContent = `${x}%`;
|
||||
}
|
||||
|
||||
private updateSpeed(speed: number) {
|
||||
let sign = this.sign(speed);
|
||||
speed = (Math.abs(speed) / 100 * 50) + 50;
|
||||
if (sign == -1) speed = 50 - speed;
|
||||
let c = Math.PI * (90 * 2);
|
||||
let pct = ((100 - speed) / 100) * c;
|
||||
this.circleBar.setAttribute('stroke-dashoffset', `${pct}`);
|
||||
}
|
||||
|
||||
// A re-implementation of Math.sign (since IE11 doesn't support it)
|
||||
private sign(num: number) {
|
||||
return num ? num < 0 ? -1 : 1 : 0;
|
||||
}
|
||||
}
|
||||
108
fieldeditors/field_turnratio.ts
Normal file
108
fieldeditors/field_turnratio.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
/// <reference path="../node_modules/pxt-core/localtypings/blockly.d.ts"/>
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
|
||||
|
||||
export interface FieldTurnRatioOptions extends Blockly.FieldCustomOptions {
|
||||
}
|
||||
|
||||
export class FieldTurnRatio extends Blockly.FieldSlider implements Blockly.FieldCustom {
|
||||
public isFieldCustom_ = true;
|
||||
|
||||
private params: any;
|
||||
|
||||
private path_: SVGPathElement;
|
||||
private reporter_: SVGTextElement;
|
||||
|
||||
/**
|
||||
* Class for a color wheel field.
|
||||
* @param {number|string} value The initial content of the field.
|
||||
* @param {Function=} opt_validator An optional function that is called
|
||||
* to validate any constraints on what the user entered. Takes the new
|
||||
* text as an argument and returns either the accepted text, a replacement
|
||||
* text, or null to abort the change.
|
||||
* @extends {Blockly.FieldNumber}
|
||||
* @constructor
|
||||
*/
|
||||
constructor(value_: any, params: FieldTurnRatioOptions, opt_validator?: Function) {
|
||||
super(String(value_), '-200', '200', null, '10', 'TurnRatio', opt_validator);
|
||||
this.params = params;
|
||||
(this as any).sliderColor_ = '#a8aaa8';
|
||||
}
|
||||
|
||||
static HALF = 80;
|
||||
static HANDLE_RADIUS = 30;
|
||||
static RADIUS = FieldTurnRatio.HALF - FieldTurnRatio.HANDLE_RADIUS - 1;
|
||||
|
||||
createLabelDom_(labelText: string) {
|
||||
let labelContainer = document.createElement('div');
|
||||
let svg = Blockly.utils.createSvgElement('svg', {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlns:html': 'http://www.w3.org/1999/xhtml',
|
||||
'xmlns:xlink': 'http://www.w3.org/1999/xlink',
|
||||
'version': '1.1',
|
||||
'height': (FieldTurnRatio.HALF + FieldTurnRatio.HANDLE_RADIUS + 10) + 'px',
|
||||
'width': (FieldTurnRatio.HALF * 2) + 'px'
|
||||
}, labelContainer);
|
||||
let defs = Blockly.utils.createSvgElement('defs', {}, svg);
|
||||
let marker = Blockly.utils.createSvgElement('marker', {
|
||||
'id': 'head',
|
||||
'orient': "auto",
|
||||
'markerWidth': '2',
|
||||
'markerHeight': '4',
|
||||
'refX': '0.1', 'refY': '1.5'
|
||||
}, defs);
|
||||
let markerPath = Blockly.utils.createSvgElement('path', {
|
||||
'd': 'M0,0 V3 L1.5,1.5 Z',
|
||||
'fill': '#f12a21'
|
||||
}, marker);
|
||||
this.reporter_ = pxsim.svg.child(svg, "text", {
|
||||
'x': FieldTurnRatio.HALF, 'y': 96,
|
||||
'text-anchor': 'middle', 'dominant-baseline': 'middle',
|
||||
'style': 'font-size: 50px',
|
||||
'class': 'sim-text inverted number'
|
||||
}) as SVGTextElement;
|
||||
this.path_ = Blockly.utils.createSvgElement('path', {
|
||||
'x1': FieldTurnRatio.HALF,
|
||||
'y1': FieldTurnRatio.HALF,
|
||||
'marker-end': 'url(#head)',
|
||||
'style': 'fill: none; stroke: #f12a21; stroke-width: 10'
|
||||
}, svg);
|
||||
this.updateGraph_();
|
||||
let readout = document.createElement('span');
|
||||
readout.setAttribute('class', 'blocklyFieldSliderReadout');
|
||||
return [labelContainer, readout];
|
||||
};
|
||||
|
||||
updateGraph_() {
|
||||
if (!this.path_) {
|
||||
return;
|
||||
}
|
||||
let v = goog.math.clamp(parseFloat(this.getText()), -200, 200);
|
||||
if (isNaN(v)) {
|
||||
v = 0;
|
||||
}
|
||||
const x = v / 100;
|
||||
const nx = Math.max(-1, Math.min(1, x));
|
||||
const theta = Math.max(nx) * Math.PI / 2;
|
||||
const r = FieldTurnRatio.RADIUS - 6;
|
||||
let cx = FieldTurnRatio.HALF;
|
||||
const cy = FieldTurnRatio.HALF - 22;
|
||||
if (Math.abs(x) > 1) {
|
||||
cx -= (x - (x > 0 ? 1 : -1)) * r / 2; // move center of circle
|
||||
}
|
||||
const alpha = 0.2 + Math.abs(nx) * 0.5;
|
||||
const y1 = r * alpha;
|
||||
const y2 = r * Math.sin(Math.PI / 2 - theta);
|
||||
const x2 = r * Math.cos(Math.PI / 2 - theta);
|
||||
const y3 = y2 - r * alpha * Math.cos(2 * theta);
|
||||
const x3 = x2 - r * alpha * Math.sin(2 * theta);
|
||||
|
||||
const d = `M ${cx} ${cy} C ${cx} ${cy - y1} ${cx + x3} ${cy - y3} ${cx + x2} ${cy - y2}`;
|
||||
this.path_.setAttribute('d', d);
|
||||
|
||||
this.reporter_.textContent = `${v}`;
|
||||
}
|
||||
|
||||
setReadout_(readout: Element, value: string) {
|
||||
this.updateGraph_();
|
||||
}
|
||||
}
|
||||
9
libs/base/enums.d.ts
vendored
9
libs/base/enums.d.ts
vendored
@@ -22,8 +22,13 @@
|
||||
}
|
||||
|
||||
|
||||
declare const enum PerfCounters {
|
||||
GC = 0,
|
||||
declare const enum ValType {
|
||||
Undefined = 0,
|
||||
Boolean = 1,
|
||||
Number = 2,
|
||||
String = 3,
|
||||
Object = 4,
|
||||
Function = 5,
|
||||
}
|
||||
|
||||
// Auto-generated. Do not edit. Really.
|
||||
|
||||
76
libs/base/shims.d.ts
vendored
76
libs/base/shims.d.ts
vendored
@@ -4,18 +4,6 @@
|
||||
|
||||
//% indexerGet=BufferMethods::getByte indexerSet=BufferMethods::setByte
|
||||
declare interface Buffer {
|
||||
/**
|
||||
* Reads an unsigned byte at a particular location
|
||||
*/
|
||||
//% shim=BufferMethods::getUint8
|
||||
getUint8(off: int32): int32;
|
||||
|
||||
/**
|
||||
* Writes an unsigned byte at a particular location
|
||||
*/
|
||||
//% shim=BufferMethods::setUint8
|
||||
setUint8(off: int32, v: int32): void;
|
||||
|
||||
/**
|
||||
* Write a number in specified format in the buffer.
|
||||
*/
|
||||
@@ -54,12 +42,6 @@ declare interface Buffer {
|
||||
//% start.defl=0 length.defl=-1 shim=BufferMethods::shift
|
||||
shift(offset: int32, start?: int32, length?: int32): void;
|
||||
|
||||
/**
|
||||
* Convert a buffer to string assuming UTF8 encoding
|
||||
*/
|
||||
//% shim=BufferMethods::toString
|
||||
toString(): string;
|
||||
|
||||
/**
|
||||
* Convert a buffer to its hexadecimal representation.
|
||||
*/
|
||||
@@ -90,13 +72,6 @@ declare namespace control {
|
||||
*/
|
||||
//% 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
|
||||
function createBufferFromUTF8(str: string): Buffer;
|
||||
}
|
||||
declare namespace loops {
|
||||
|
||||
@@ -126,12 +101,6 @@ declare namespace control {
|
||||
//% blockId=control_running_time block="millis (ms)" shim=control::millis
|
||||
function millis(): int32;
|
||||
|
||||
/**
|
||||
* Gets current time in microseconds. Overflows every ~18 minutes.
|
||||
*/
|
||||
//% shim=control::micros
|
||||
function micros(): int32;
|
||||
|
||||
/**
|
||||
* Used internally
|
||||
*/
|
||||
@@ -174,54 +143,11 @@ declare namespace control {
|
||||
//% help=control/device-serial-number shim=control::deviceSerialNumber
|
||||
function deviceSerialNumber(): int32;
|
||||
|
||||
/**
|
||||
* Derive a unique, consistent 64-bit serial number of this device from internal data.
|
||||
*/
|
||||
//% blockId="control_device_long_serial_number" block="device long serial number" weight=9
|
||||
//% help=control/device-long-serial-number shim=control::deviceLongSerialNumber
|
||||
function deviceLongSerialNumber(): Buffer;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
//% shim=control::__log
|
||||
function __log(prority: int32, text: string): void;
|
||||
|
||||
/**
|
||||
* Dump internal information about a value.
|
||||
*/
|
||||
//% shim=control::dmesgValue
|
||||
function dmesgValue(v: any): void;
|
||||
|
||||
/**
|
||||
* Force GC and dump basic information about heap.
|
||||
*/
|
||||
//% shim=control::gc
|
||||
function gc(): void;
|
||||
|
||||
/**
|
||||
* Force GC and halt waiting for debugger to do a full heap dump.
|
||||
*/
|
||||
//% shim=control::heapDump
|
||||
function heapDump(): void;
|
||||
|
||||
/**
|
||||
* Set flags used when connecting an external debugger.
|
||||
*/
|
||||
//% shim=control::setDebugFlags
|
||||
function setDebugFlags(flags: int32): void;
|
||||
|
||||
/**
|
||||
* Record a heap snapshot to debug memory leaks.
|
||||
*/
|
||||
//% shim=control::heapSnapshot
|
||||
function heapSnapshot(): void;
|
||||
|
||||
/**
|
||||
* Return true if profiling is enabled in the current build.
|
||||
*/
|
||||
//% shim=control::profilingEnabled
|
||||
function profilingEnabled(): boolean;
|
||||
function __log(text: string): void;
|
||||
}
|
||||
|
||||
// Auto-generated. Do not edit. Really.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const enum ColorSensorMode {
|
||||
None = 0,
|
||||
//% block="reflected light intensity"
|
||||
ReflectedLightIntensity = 0,
|
||||
//% block="ambient light intensity"
|
||||
@@ -58,6 +59,7 @@ namespace sensors {
|
||||
|
||||
constructor(port: number) {
|
||||
super(port)
|
||||
this._setMode(ColorSensorMode.None);
|
||||
this.thresholdDetector = new sensors.ThresholdDetector(this.id());
|
||||
this.calibrating = false;
|
||||
}
|
||||
@@ -179,22 +181,6 @@ namespace sensors {
|
||||
return this.getNumber(NumberFormat.UInt8LE, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the color is being detected
|
||||
* @param color the color to detect
|
||||
*/
|
||||
//% help=sensors/color-sensor/is-color-detected
|
||||
//% block="is **color sensor** %this|detected|%color=colorEnumPicker"
|
||||
//% blockId=colorisColorDetectedDetected
|
||||
//% parts="colorsensor"
|
||||
//% blockNamespace=sensors
|
||||
//% this.fieldEditor="ports"
|
||||
//% weight=99 blockGap=8
|
||||
//% group="Color Sensor"
|
||||
isColorDetected(color: number) {
|
||||
return this.color() == color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current raw rgb values as an array from the color sensor.
|
||||
* @param sensor the color sensor to query the request
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
# Is Color Detected
|
||||
|
||||
Checks the color is detected
|
||||
|
||||
```sig
|
||||
let b = sensors.color1.isColorDetected(ColorSensorColor.Blue)
|
||||
```
|
||||
|
||||
The [color](/reference/sensors/color) you choose to look for is one of the colors that the sensor can detect. If you want to use colors for tracking, it's best to use a color that is the same or very close to the ones the sensor detects.
|
||||
|
||||
## Parameters
|
||||
|
||||
* **color**: the [color](/reference/sensors/color) to watch for.
|
||||
|
||||
## Example
|
||||
|
||||
Wait for the sensor to see ``blue``. Then, show an expression on the screen.
|
||||
|
||||
```blocks
|
||||
brick.showString("Waiting for blue", 1)
|
||||
while(!sensors.color1.isColorDetected(ColorSensorColor.Blue)) {
|
||||
pause(20)
|
||||
}
|
||||
brick.clearScreen()
|
||||
brick.showImage(images.expressionsSick)
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
[on color detected](/reference/sensors/color-sensor/on-color-detected), [color](/reference/sensors/color)
|
||||
@@ -26,7 +26,6 @@ namespace brick {
|
||||
*/
|
||||
//% blockId=brickBatteryProperty block="battery %property"
|
||||
//% group="Battery"
|
||||
//% blockGap=8
|
||||
//% help=brick/battery-property
|
||||
export function batteryInfo(property: BatteryProperty): number {
|
||||
const info = sensors.internal.getBatteryInfo();
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace brick {
|
||||
//% blockId=buttonIsPressed
|
||||
//% parts="brick"
|
||||
//% blockNamespace=brick
|
||||
//% weight=81
|
||||
//% weight=81 blockGap=8
|
||||
//% group="Buttons"
|
||||
//% button.fieldEditor="brickbuttons"
|
||||
isPressed() {
|
||||
|
||||
40
libs/core/control.cpp
Normal file
40
libs/core/control.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "pxt.h"
|
||||
|
||||
namespace control {
|
||||
|
||||
/**
|
||||
* Announce that an event happened to registered handlers.
|
||||
* @param src ID of the Component that generated the event
|
||||
* @param value Component specific code indicating the cause of the event.
|
||||
* @param mode optional definition of how the event should be processed after construction.
|
||||
*/
|
||||
//% weight=21 blockGap=12 blockId="control_raise_event"
|
||||
//% block="raise event|from %src|with value %value" blockExternalInputs=1
|
||||
//% help=control/raise-event
|
||||
void raiseEvent(int src, int value) {
|
||||
pxt::raiseEvent(src, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates the next user notification event
|
||||
*/
|
||||
//% help=control/allocate-notify-event
|
||||
int allocateNotifyEvent() {
|
||||
return pxt::allocateNotifyEvent();
|
||||
}
|
||||
|
||||
/** Write data to DMESG debugging buffer. */
|
||||
//%
|
||||
void dmesg(String s) {
|
||||
DMESG("# %s", s->data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace serial {
|
||||
/** Send DMESG debug buffer over serial. */
|
||||
//%
|
||||
void writeDmesg() {
|
||||
pxt::dumpDmesg();
|
||||
}
|
||||
}
|
||||
407
libs/core/dal.d.ts
vendored
407
libs/core/dal.d.ts
vendored
@@ -1,305 +1,6 @@
|
||||
// Auto-generated. Do not edit.
|
||||
declare const enum DAL {
|
||||
// /pxtapp/configkeys.h
|
||||
CFG_PIN_NAME_MSK = 65535,
|
||||
CFG_PIN_CONFIG_MSK = 4294901760,
|
||||
CFG_PIN_CONFIG_ACTIVE_LO = 65536,
|
||||
CFG_MAGIC0 = 513675505,
|
||||
CFG_MAGIC1 = 539130489,
|
||||
CFG_PIN_ACCELEROMETER_INT = 1,
|
||||
CFG_PIN_ACCELEROMETER_SCL = 2,
|
||||
CFG_PIN_ACCELEROMETER_SDA = 3,
|
||||
CFG_PIN_BTN_A = 4,
|
||||
CFG_PIN_BTN_B = 5,
|
||||
CFG_PIN_BTN_SLIDE = 6,
|
||||
CFG_PIN_DOTSTAR_CLOCK = 7,
|
||||
CFG_PIN_DOTSTAR_DATA = 8,
|
||||
CFG_PIN_FLASH_CS = 9,
|
||||
CFG_PIN_FLASH_MISO = 10,
|
||||
CFG_PIN_FLASH_MOSI = 11,
|
||||
CFG_PIN_FLASH_SCK = 12,
|
||||
CFG_PIN_LED = 13,
|
||||
CFG_PIN_LIGHT = 14,
|
||||
CFG_PIN_MICROPHONE = 15,
|
||||
CFG_PIN_MIC_CLOCK = 16,
|
||||
CFG_PIN_MIC_DATA = 17,
|
||||
CFG_PIN_MISO = 18,
|
||||
CFG_PIN_MOSI = 19,
|
||||
CFG_PIN_NEOPIXEL = 20,
|
||||
CFG_PIN_RX = 21,
|
||||
CFG_PIN_RXLED = 22,
|
||||
CFG_PIN_SCK = 23,
|
||||
CFG_PIN_SCL = 24,
|
||||
CFG_PIN_SDA = 25,
|
||||
CFG_PIN_SPEAKER_AMP = 26,
|
||||
CFG_PIN_TEMPERATURE = 27,
|
||||
CFG_PIN_TX = 28,
|
||||
CFG_PIN_TXLED = 29,
|
||||
CFG_PIN_IR_OUT = 30,
|
||||
CFG_PIN_IR_IN = 31,
|
||||
CFG_PIN_DISPLAY_SCK = 32,
|
||||
CFG_PIN_DISPLAY_MISO = 33,
|
||||
CFG_PIN_DISPLAY_MOSI = 34,
|
||||
CFG_PIN_DISPLAY_CS = 35,
|
||||
CFG_PIN_DISPLAY_DC = 36,
|
||||
CFG_DISPLAY_WIDTH = 37,
|
||||
CFG_DISPLAY_HEIGHT = 38,
|
||||
CFG_DISPLAY_CFG0 = 39,
|
||||
CFG_DISPLAY_CFG1 = 40,
|
||||
CFG_DISPLAY_CFG2 = 41,
|
||||
CFG_DISPLAY_CFG3 = 42,
|
||||
CFG_PIN_DISPLAY_RST = 43,
|
||||
CFG_PIN_DISPLAY_BL = 44,
|
||||
CFG_PIN_SERVO_1 = 45,
|
||||
CFG_PIN_SERVO_2 = 46,
|
||||
CFG_PIN_BTN_LEFT = 47,
|
||||
CFG_PIN_BTN_RIGHT = 48,
|
||||
CFG_PIN_BTN_UP = 49,
|
||||
CFG_PIN_BTN_DOWN = 50,
|
||||
CFG_PIN_BTN_MENU = 51,
|
||||
CFG_PIN_LED_R = 52,
|
||||
CFG_PIN_LED_G = 53,
|
||||
CFG_PIN_LED_B = 54,
|
||||
CFG_PIN_LED1 = 55,
|
||||
CFG_PIN_LED2 = 56,
|
||||
CFG_PIN_LED3 = 57,
|
||||
CFG_PIN_LED4 = 58,
|
||||
CFG_SPEAKER_VOLUME = 59,
|
||||
CFG_PIN_JACK_TX = 60,
|
||||
CFG_PIN_JACK_SENSE = 61,
|
||||
CFG_PIN_JACK_HPEN = 62,
|
||||
CFG_PIN_JACK_BZEN = 63,
|
||||
CFG_PIN_JACK_PWREN = 64,
|
||||
CFG_PIN_JACK_SND = 65,
|
||||
CFG_PIN_JACK_BUSLED = 66,
|
||||
CFG_PIN_JACK_COMMLED = 67,
|
||||
CFG_PIN_BTN_SOFT_RESET = 69,
|
||||
CFG_ACCELEROMETER_TYPE = 70,
|
||||
CFG_PIN_BTNMX_LATCH = 71,
|
||||
CFG_PIN_BTNMX_CLOCK = 72,
|
||||
CFG_PIN_BTNMX_DATA = 73,
|
||||
CFG_PIN_BTN_MENU2 = 74,
|
||||
CFG_PIN_BATTSENSE = 75,
|
||||
CFG_PIN_VIBRATION = 76,
|
||||
CFG_PIN_PWREN = 77,
|
||||
CFG_DISPLAY_TYPE = 78,
|
||||
CFG_PIN_ROTARY_ENCODER_A = 79,
|
||||
CFG_PIN_ROTARY_ENCODER_B = 80,
|
||||
CFG_ACCELEROMETER_SPACE = 81,
|
||||
CFG_PIN_WIFI_MOSI = 82,
|
||||
CFG_PIN_WIFI_MISO = 83,
|
||||
CFG_PIN_WIFI_SCK = 84,
|
||||
CFG_PIN_WIFI_TX = 85,
|
||||
CFG_PIN_WIFI_RX = 86,
|
||||
CFG_PIN_WIFI_CS = 87,
|
||||
CFG_PIN_WIFI_BUSY = 88,
|
||||
CFG_PIN_WIFI_RESET = 89,
|
||||
CFG_PIN_WIFI_GPIO0 = 90,
|
||||
CFG_PIN_WIFI_AT_TX = 91,
|
||||
CFG_PIN_WIFI_AT_RX = 92,
|
||||
CFG_PIN_USB_POWER = 93,
|
||||
ACCELEROMETER_TYPE_LIS3DH = 50,
|
||||
ACCELEROMETER_TYPE_LIS3DH_ALT = 48,
|
||||
ACCELEROMETER_TYPE_MMA8453 = 56,
|
||||
ACCELEROMETER_TYPE_FXOS8700 = 60,
|
||||
ACCELEROMETER_TYPE_MMA8653 = 58,
|
||||
ACCELEROMETER_TYPE_MSA300 = 76,
|
||||
ACCELEROMETER_TYPE_MPU6050 = 104,
|
||||
DISPLAY_TYPE_ST7735 = 7735,
|
||||
DISPLAY_TYPE_ILI9341 = 9341,
|
||||
CFG_PIN_A0 = 100,
|
||||
CFG_PIN_A1 = 101,
|
||||
CFG_PIN_A2 = 102,
|
||||
CFG_PIN_A3 = 103,
|
||||
CFG_PIN_A4 = 104,
|
||||
CFG_PIN_A5 = 105,
|
||||
CFG_PIN_A6 = 106,
|
||||
CFG_PIN_A7 = 107,
|
||||
CFG_PIN_A8 = 108,
|
||||
CFG_PIN_A9 = 109,
|
||||
CFG_PIN_A10 = 110,
|
||||
CFG_PIN_A11 = 111,
|
||||
CFG_PIN_A12 = 112,
|
||||
CFG_PIN_A13 = 113,
|
||||
CFG_PIN_A14 = 114,
|
||||
CFG_PIN_A15 = 115,
|
||||
CFG_PIN_A16 = 116,
|
||||
CFG_PIN_A17 = 117,
|
||||
CFG_PIN_A18 = 118,
|
||||
CFG_PIN_A19 = 119,
|
||||
CFG_PIN_A20 = 120,
|
||||
CFG_PIN_A21 = 121,
|
||||
CFG_PIN_A22 = 122,
|
||||
CFG_PIN_A23 = 123,
|
||||
CFG_PIN_A24 = 124,
|
||||
CFG_PIN_A25 = 125,
|
||||
CFG_PIN_A26 = 126,
|
||||
CFG_PIN_A27 = 127,
|
||||
CFG_PIN_A28 = 128,
|
||||
CFG_PIN_A29 = 129,
|
||||
CFG_PIN_A30 = 130,
|
||||
CFG_PIN_A31 = 131,
|
||||
CFG_PIN_D0 = 150,
|
||||
CFG_PIN_D1 = 151,
|
||||
CFG_PIN_D2 = 152,
|
||||
CFG_PIN_D3 = 153,
|
||||
CFG_PIN_D4 = 154,
|
||||
CFG_PIN_D5 = 155,
|
||||
CFG_PIN_D6 = 156,
|
||||
CFG_PIN_D7 = 157,
|
||||
CFG_PIN_D8 = 158,
|
||||
CFG_PIN_D9 = 159,
|
||||
CFG_PIN_D10 = 160,
|
||||
CFG_PIN_D11 = 161,
|
||||
CFG_PIN_D12 = 162,
|
||||
CFG_PIN_D13 = 163,
|
||||
CFG_PIN_D14 = 164,
|
||||
CFG_PIN_D15 = 165,
|
||||
CFG_PIN_D16 = 166,
|
||||
CFG_PIN_D17 = 167,
|
||||
CFG_PIN_D18 = 168,
|
||||
CFG_PIN_D19 = 169,
|
||||
CFG_PIN_D20 = 170,
|
||||
CFG_PIN_D21 = 171,
|
||||
CFG_PIN_D22 = 172,
|
||||
CFG_PIN_D23 = 173,
|
||||
CFG_PIN_D24 = 174,
|
||||
CFG_PIN_D25 = 175,
|
||||
CFG_PIN_D26 = 176,
|
||||
CFG_PIN_D27 = 177,
|
||||
CFG_PIN_D28 = 178,
|
||||
CFG_PIN_D29 = 179,
|
||||
CFG_PIN_D30 = 180,
|
||||
CFG_PIN_D31 = 181,
|
||||
CFG_NUM_NEOPIXELS = 200,
|
||||
CFG_NUM_DOTSTARS = 201,
|
||||
CFG_DEFAULT_BUTTON_MODE = 202,
|
||||
CFG_SWD_ENABLED = 203,
|
||||
CFG_FLASH_BYTES = 204,
|
||||
CFG_RAM_BYTES = 205,
|
||||
CFG_SYSTEM_HEAP_BYTES = 206,
|
||||
CFG_LOW_MEM_SIMULATION_KB = 207,
|
||||
CFG_BOOTLOADER_BOARD_ID = 208,
|
||||
CFG_UF2_FAMILY = 209,
|
||||
CFG_PINS_PORT_SIZE = 210,
|
||||
CFG_BOOTLOADER_PROTECTION = 211,
|
||||
CFG_POWER_DEEPSLEEP_TIMEOUT = 212,
|
||||
CFG_ANALOG_BUTTON_THRESHOLD = 213,
|
||||
CFG_CPU_MHZ = 214,
|
||||
CFG_CONTROLLER_LIGHT_MAX_BRIGHTNESS = 215,
|
||||
CFG_PIN_B0 = 300,
|
||||
CFG_PIN_B1 = 301,
|
||||
CFG_PIN_B2 = 302,
|
||||
CFG_PIN_B3 = 303,
|
||||
CFG_PIN_B4 = 304,
|
||||
CFG_PIN_B5 = 305,
|
||||
CFG_PIN_B6 = 306,
|
||||
CFG_PIN_B7 = 307,
|
||||
CFG_PIN_B8 = 308,
|
||||
CFG_PIN_B9 = 309,
|
||||
CFG_PIN_B10 = 310,
|
||||
CFG_PIN_B11 = 311,
|
||||
CFG_PIN_B12 = 312,
|
||||
CFG_PIN_B13 = 313,
|
||||
CFG_PIN_B14 = 314,
|
||||
CFG_PIN_B15 = 315,
|
||||
CFG_PIN_B16 = 316,
|
||||
CFG_PIN_B17 = 317,
|
||||
CFG_PIN_B18 = 318,
|
||||
CFG_PIN_B19 = 319,
|
||||
CFG_PIN_B20 = 320,
|
||||
CFG_PIN_B21 = 321,
|
||||
CFG_PIN_B22 = 322,
|
||||
CFG_PIN_B23 = 323,
|
||||
CFG_PIN_B24 = 324,
|
||||
CFG_PIN_B25 = 325,
|
||||
CFG_PIN_B26 = 326,
|
||||
CFG_PIN_B27 = 327,
|
||||
CFG_PIN_B28 = 328,
|
||||
CFG_PIN_B29 = 329,
|
||||
CFG_PIN_B30 = 330,
|
||||
CFG_PIN_B31 = 331,
|
||||
CFG_PIN_C0 = 350,
|
||||
CFG_PIN_C1 = 351,
|
||||
CFG_PIN_C2 = 352,
|
||||
CFG_PIN_C3 = 353,
|
||||
CFG_PIN_C4 = 354,
|
||||
CFG_PIN_C5 = 355,
|
||||
CFG_PIN_C6 = 356,
|
||||
CFG_PIN_C7 = 357,
|
||||
CFG_PIN_C8 = 358,
|
||||
CFG_PIN_C9 = 359,
|
||||
CFG_PIN_C10 = 360,
|
||||
CFG_PIN_C11 = 361,
|
||||
CFG_PIN_C12 = 362,
|
||||
CFG_PIN_C13 = 363,
|
||||
CFG_PIN_C14 = 364,
|
||||
CFG_PIN_C15 = 365,
|
||||
CFG_PIN_C16 = 366,
|
||||
CFG_PIN_C17 = 367,
|
||||
CFG_PIN_C18 = 368,
|
||||
CFG_PIN_C19 = 369,
|
||||
CFG_PIN_C20 = 370,
|
||||
CFG_PIN_C21 = 371,
|
||||
CFG_PIN_C22 = 372,
|
||||
CFG_PIN_C23 = 373,
|
||||
CFG_PIN_C24 = 374,
|
||||
CFG_PIN_C25 = 375,
|
||||
CFG_PIN_C26 = 376,
|
||||
CFG_PIN_C27 = 377,
|
||||
CFG_PIN_C28 = 378,
|
||||
CFG_PIN_C29 = 379,
|
||||
CFG_PIN_C30 = 380,
|
||||
CFG_PIN_C31 = 381,
|
||||
CFG_PIN_P0 = 400,
|
||||
CFG_PIN_P1 = 401,
|
||||
CFG_PIN_P2 = 402,
|
||||
CFG_PIN_P3 = 403,
|
||||
CFG_PIN_P4 = 404,
|
||||
CFG_PIN_P5 = 405,
|
||||
CFG_PIN_P6 = 406,
|
||||
CFG_PIN_P7 = 407,
|
||||
CFG_PIN_P8 = 408,
|
||||
CFG_PIN_P9 = 409,
|
||||
CFG_PIN_P10 = 410,
|
||||
CFG_PIN_P11 = 411,
|
||||
CFG_PIN_P12 = 412,
|
||||
CFG_PIN_P13 = 413,
|
||||
CFG_PIN_P14 = 414,
|
||||
CFG_PIN_P15 = 415,
|
||||
CFG_PIN_P16 = 416,
|
||||
CFG_PIN_P17 = 417,
|
||||
CFG_PIN_P18 = 418,
|
||||
CFG_PIN_P19 = 419,
|
||||
CFG_PIN_P20 = 420,
|
||||
CFG_PIN_P21 = 421,
|
||||
CFG_PIN_P22 = 422,
|
||||
CFG_PIN_P23 = 423,
|
||||
CFG_PIN_P24 = 424,
|
||||
CFG_PIN_P25 = 425,
|
||||
CFG_PIN_P26 = 426,
|
||||
CFG_PIN_P27 = 427,
|
||||
CFG_PIN_P28 = 428,
|
||||
CFG_PIN_P29 = 429,
|
||||
CFG_PIN_P30 = 430,
|
||||
CFG_PIN_P31 = 431,
|
||||
CFG_PIN_LORA_MISO = 1001,
|
||||
CFG_PIN_LORA_MOSI = 1002,
|
||||
CFG_PIN_LORA_SCK = 1003,
|
||||
CFG_PIN_LORA_CS = 1004,
|
||||
CFG_PIN_LORA_BOOT = 1005,
|
||||
CFG_PIN_LORA_RESET = 1006,
|
||||
CFG_PIN_IRRXLED = 1007,
|
||||
CFG_PIN_IRTXLED = 1008,
|
||||
CFG_PIN_LCD_RESET = 1009,
|
||||
CFG_PIN_LCD_ENABLE = 1010,
|
||||
CFG_PIN_LCD_DATALINE4 = 1011,
|
||||
CFG_PIN_LCD_DATALINE5 = 1012,
|
||||
CFG_PIN_LCD_DATALINE6 = 1013,
|
||||
CFG_PIN_LCD_DATALINE7 = 1014,
|
||||
CFG_NUM_LCD_COLUMNS = 1015,
|
||||
CFG_NUM_LCD_ROWS = 1016,
|
||||
// /pxtapp/ev3const.h
|
||||
// built/dockermake/pxtapp/ev3const.h
|
||||
NUM_INPUTS = 4,
|
||||
NUM_OUTPUTS = 4,
|
||||
LCD_WIDTH = 178,
|
||||
@@ -345,66 +46,44 @@ declare const enum DAL {
|
||||
CONN_OUTPUT_TACHO = 125,
|
||||
CONN_NONE = 126,
|
||||
CONN_ERROR = 127,
|
||||
opProgramStart = 3,
|
||||
opOutputGetType = 160,
|
||||
opOutputSetType = 161,
|
||||
opOutputReset = 162,
|
||||
opOutputStop = 163,
|
||||
opOutputPower = 164,
|
||||
opOutputSpeed = 165,
|
||||
opOutputStart = 166,
|
||||
opOutputPolarity = 167,
|
||||
opOutputRead = 168,
|
||||
opOutputTest = 169,
|
||||
opOutputReady = 170,
|
||||
opOutputPosition = 171,
|
||||
opOutputStepPower = 172,
|
||||
opOutputTimePower = 173,
|
||||
opOutputStepSpeed = 174,
|
||||
opOutputTimeSpeed = 175,
|
||||
opOutputStepSync = 176,
|
||||
opOutputTimeSync = 177,
|
||||
opOutputClearCount = 178,
|
||||
opOutputGetCount = 179,
|
||||
opOutputProgramStop = 180,
|
||||
BUTTON_ID_UP = 1,
|
||||
BUTTON_ID_ENTER = 2,
|
||||
BUTTON_ID_DOWN = 4,
|
||||
BUTTON_ID_RIGHT = 8,
|
||||
BUTTON_ID_LEFT = 16,
|
||||
BUTTON_ID_ESCAPE = 32,
|
||||
// /pxtapp/platform.h
|
||||
PXT_GC_THREAD_LIST = 1,
|
||||
// /pxtapp/pxt.h
|
||||
opProgramStart = 0x03,
|
||||
opOutputGetType = 0xA0,
|
||||
opOutputSetType = 0xA1,
|
||||
opOutputReset = 0xA2,
|
||||
opOutputStop = 0xA3,
|
||||
opOutputPower = 0xA4,
|
||||
opOutputSpeed = 0xA5,
|
||||
opOutputStart = 0xA6,
|
||||
opOutputPolarity = 0xA7,
|
||||
opOutputRead = 0xA8,
|
||||
opOutputTest = 0xA9,
|
||||
opOutputReady = 0xAA,
|
||||
opOutputPosition = 0xAB,
|
||||
opOutputStepPower = 0xAC,
|
||||
opOutputTimePower = 0xAD,
|
||||
opOutputStepSpeed = 0xAE,
|
||||
opOutputTimeSpeed = 0xAF,
|
||||
opOutputStepSync = 0xB0,
|
||||
opOutputTimeSync = 0xB1,
|
||||
opOutputClearCount = 0xB2,
|
||||
opOutputGetCount = 0xB3,
|
||||
opOutputProgramStop = 0xB4,
|
||||
BUTTON_ID_UP = 0x01,
|
||||
BUTTON_ID_ENTER = 0x02,
|
||||
BUTTON_ID_DOWN = 0x04,
|
||||
BUTTON_ID_RIGHT = 0x08,
|
||||
BUTTON_ID_LEFT = 0x10,
|
||||
BUTTON_ID_ESCAPE = 0x20,
|
||||
// built/dockermake/pxtapp/pxt.h
|
||||
DEVICE_EVT_ANY = 0,
|
||||
DEVICE_ID_NOTIFY = 10000,
|
||||
DEVICE_ID_NOTIFY_ONE = 10001,
|
||||
IMAGE_BITS = 1,
|
||||
// /pxtapp/pxtbase.h
|
||||
PXT32 = 1,
|
||||
PXT64 = 1,
|
||||
PXT_VTABLE_SHIFT = 2,
|
||||
PXT_REFCNT_FLASH = 65534,
|
||||
VTABLE_MAGIC = 249,
|
||||
Undefined = 0,
|
||||
Boolean = 1,
|
||||
Number = 2,
|
||||
String = 3,
|
||||
Object = 4,
|
||||
Function = 5,
|
||||
BoxedString = 1,
|
||||
BoxedNumber = 2,
|
||||
BoxedBuffer = 3,
|
||||
RefAction = 4,
|
||||
RefImage = 5,
|
||||
RefCollection = 6,
|
||||
RefRefLocal = 7,
|
||||
RefMap = 8,
|
||||
RefMImage = 9,
|
||||
MMap = 10,
|
||||
User0 = 16,
|
||||
PXT_IOS_HEAP_ALLOC_BITS = 20,
|
||||
IMAGE_HEADER_MAGIC = 135,
|
||||
// built/dockermake/pxtapp/pxtbase.h
|
||||
PXT_REF_TAG_STRING = 1,
|
||||
PXT_REF_TAG_BUFFER = 2,
|
||||
PXT_REF_TAG_IMAGE = 3,
|
||||
PXT_REF_TAG_NUMBER = 32,
|
||||
PXT_REF_TAG_ACTION = 33,
|
||||
Int8LE = 1,
|
||||
UInt8LE = 2,
|
||||
Int16LE = 3,
|
||||
@@ -421,10 +100,12 @@ declare const enum DAL {
|
||||
Float64LE = 14,
|
||||
Float32BE = 15,
|
||||
Float64BE = 16,
|
||||
NUM_TRY_FRAME_REGS = 3,
|
||||
GC = 0,
|
||||
// /pxtapp/pxtconfig.h
|
||||
PXT_GC = 1,
|
||||
// /pxtapp/pxtcore.h
|
||||
PXT_HARD_FLOAT = 1,
|
||||
Undefined = 0,
|
||||
Boolean = 1,
|
||||
Number = 2,
|
||||
String = 3,
|
||||
Object = 4,
|
||||
Function = 5,
|
||||
// built/dockermake/pxtapp/pxtconfig.h
|
||||
// built/dockermake/pxtapp/pxtcore.h
|
||||
}
|
||||
|
||||
@@ -208,14 +208,12 @@ namespace sensors.internal {
|
||||
}
|
||||
}
|
||||
|
||||
export interface BatteryInfo {
|
||||
export function getBatteryInfo(): {
|
||||
level: number;
|
||||
Ibatt: number,
|
||||
Vbatt: number,
|
||||
Imotor: number
|
||||
}
|
||||
|
||||
export function getBatteryInfo(): BatteryInfo {
|
||||
} {
|
||||
init();
|
||||
if (!batteryInfo) updateBatteryInfo();
|
||||
const CinCnt = batteryInfo.CinCnt;
|
||||
@@ -277,25 +275,22 @@ void cUiUpdatePower(void)
|
||||
const conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
|
||||
let r = 0;
|
||||
for (let i = 0; i < conns.length; ++i) {
|
||||
r = conns[i] + (r << 6) + (r << 16) - r;
|
||||
r = (r << 8 | conns[i]);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
let nonActivated = 0;
|
||||
function detectDevices() {
|
||||
control.dmesg(`detect devices (hash ${hashDevices()})`)
|
||||
//control.dmesg(`detect devices (${nonActivated} na)`)
|
||||
const conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
|
||||
let numChanged = 0;
|
||||
const uartSensors: SensorInfo[] = [];
|
||||
|
||||
for (const sensorInfo of sensorInfos) {
|
||||
const newConn = conns[sensorInfo.port]
|
||||
if (newConn == sensorInfo.connType
|
||||
&& sensorInfo.sensor
|
||||
&& sensorInfo.sensor.isActive()) {
|
||||
if (newConn == DAL.CONN_INPUT_UART)
|
||||
uartSensors.push(sensorInfo);
|
||||
if (newConn == sensorInfo.connType) {
|
||||
// control.dmesg(`connection unchanged ${newConn} at ${sensorInfo.port}`)
|
||||
continue;
|
||||
}
|
||||
numChanged++
|
||||
@@ -326,8 +321,7 @@ void cUiUpdatePower(void)
|
||||
for (const sensorInfo of uartSensors) {
|
||||
let uinfo = readUartInfo(sensorInfo.port, 0)
|
||||
sensorInfo.devType = uinfo[TypesOff.Type]
|
||||
const mode = uinfo[TypesOff.Mode];
|
||||
control.dmesg(`UART type ${sensorInfo.devType} mode ${mode}`)
|
||||
control.dmesg(`UART type ${sensorInfo.devType}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,7 +456,7 @@ void cUiUpdatePower(void)
|
||||
|
||||
reset() {
|
||||
if (this.isActive()) uartReset(this._port);
|
||||
this.realmode = -1;
|
||||
this.realmode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,6 +534,8 @@ void cUiUpdatePower(void)
|
||||
|
||||
function uartClearChange(port: number) {
|
||||
control.dmesg(`UART clear change`);
|
||||
const UART_DATA_READY = 8
|
||||
const UART_PORT_CHANGED = 1
|
||||
while (true) {
|
||||
let status = getUartStatus(port)
|
||||
if (port < 0) break
|
||||
@@ -560,7 +556,7 @@ void cUiUpdatePower(void)
|
||||
}
|
||||
|
||||
function setUartModes() {
|
||||
control.dmesg(`UART set modes 0x${devcon.toHex()}`)
|
||||
control.dmesg(`UART set modes`)
|
||||
uartMM.ioctl(IO.UART_SET_CONN, devcon)
|
||||
const ports: number[] = [];
|
||||
for (let port = 0; port < DAL.NUM_INPUTS; ++port) {
|
||||
@@ -572,26 +568,22 @@ void cUiUpdatePower(void)
|
||||
while (ports.length) {
|
||||
const port = ports.pop();
|
||||
const status = waitNonZeroUartStatus(port)
|
||||
control.dmesg(`UART status ${status} at ${port}`);
|
||||
if (!(status & UART_DATA_READY))
|
||||
setUartMode(port, devcon[DevConOff.Mode + port]);
|
||||
control.dmesg(`UART set mode ${status} at ${port}`);
|
||||
}
|
||||
}
|
||||
|
||||
function updateUartMode(port: number, mode: number) {
|
||||
control.dmesg(`UART update mode to ${mode} at ${port}`)
|
||||
control.dmesg(`UART set mode to ${mode} at ${port}`)
|
||||
devcon.setNumber(NumberFormat.Int8LE, DevConOff.Connection + port, DAL.CONN_INPUT_UART)
|
||||
devcon.setNumber(NumberFormat.Int8LE, DevConOff.Type + port, 33)
|
||||
devcon.setNumber(NumberFormat.Int8LE, DevConOff.Mode + port, mode)
|
||||
}
|
||||
|
||||
const UART_PORT_CHANGED = 1
|
||||
const UART_DATA_READY = 8
|
||||
function setUartMode(port: number, mode: number) {
|
||||
const UART_PORT_CHANGED = 1
|
||||
while (true) {
|
||||
if (port < 0) return
|
||||
updateUartMode(port, mode);
|
||||
control.dmesg(`UART set mode 0x${devcon.toHex()}`)
|
||||
uartMM.ioctl(IO.UART_SET_CONN, devcon)
|
||||
let status = waitNonZeroUartStatus(port)
|
||||
if (status & UART_PORT_CHANGED) {
|
||||
@@ -599,8 +591,7 @@ void cUiUpdatePower(void)
|
||||
uartClearChange(port)
|
||||
} else {
|
||||
control.dmesg(`UART status ${status}`);
|
||||
if (status & UART_DATA_READY)
|
||||
break;
|
||||
break;
|
||||
}
|
||||
pause(10)
|
||||
}
|
||||
|
||||
589
libs/core/linux.cpp
Normal file
589
libs/core/linux.cpp
Normal file
@@ -0,0 +1,589 @@
|
||||
#include "pxt.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <cstdarg>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <malloc.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "ev3const.h"
|
||||
|
||||
#define THREAD_DBG(...)
|
||||
|
||||
#define MALLOC_LIMIT (8 * 1024 * 1024)
|
||||
#define MALLOC_CHECK_PERIOD (1024 * 1024)
|
||||
|
||||
void *xmalloc(size_t sz) {
|
||||
static size_t allocBytes = 0;
|
||||
allocBytes += sz;
|
||||
if (allocBytes >= MALLOC_CHECK_PERIOD) {
|
||||
allocBytes = 0;
|
||||
auto info = mallinfo();
|
||||
DMESG("malloc used: %d kb", info.uordblks / 1024);
|
||||
if (info.uordblks > MALLOC_LIMIT) {
|
||||
target_panic(904);
|
||||
}
|
||||
}
|
||||
auto r = malloc(sz);
|
||||
if (r == NULL)
|
||||
target_panic(905); // shouldn't happen
|
||||
return r;
|
||||
}
|
||||
|
||||
void *operator new(size_t size) {
|
||||
return xmalloc(size);
|
||||
}
|
||||
void *operator new[](size_t size) {
|
||||
return xmalloc(size);
|
||||
}
|
||||
|
||||
void operator delete(void *p) {
|
||||
free(p);
|
||||
}
|
||||
void operator delete[](void *p) {
|
||||
free(p);
|
||||
}
|
||||
|
||||
namespace pxt {
|
||||
|
||||
static int startTime;
|
||||
static pthread_mutex_t execMutex;
|
||||
static pthread_mutex_t eventMutex;
|
||||
static pthread_cond_t newEventBroadcast;
|
||||
|
||||
struct Thread {
|
||||
struct Thread *next;
|
||||
Action act;
|
||||
TValue arg0;
|
||||
pthread_t pid;
|
||||
pthread_cond_t waitCond;
|
||||
int waitSource;
|
||||
int waitValue;
|
||||
TValue data0;
|
||||
TValue data1;
|
||||
};
|
||||
|
||||
static struct Thread *allThreads;
|
||||
static struct Event *eventHead, *eventTail;
|
||||
static int usbFD;
|
||||
static int dmesgPtr;
|
||||
static int dmesgSerialPtr;
|
||||
static char dmesgBuf[4096];
|
||||
|
||||
struct Event {
|
||||
struct Event *next;
|
||||
int source;
|
||||
int value;
|
||||
};
|
||||
|
||||
Event lastEvent;
|
||||
|
||||
Event *mkEvent(int source, int value) {
|
||||
auto res = new Event();
|
||||
memset(res, 0, sizeof(Event));
|
||||
res->source = source;
|
||||
res->value = value;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define USB_MAGIC 0x3d3f
|
||||
#define USB_SERIAL 1
|
||||
#define USB_RESTART 2
|
||||
#define USB_DMESG 3
|
||||
|
||||
struct UsbPacket {
|
||||
uint16_t size;
|
||||
uint16_t msgcount;
|
||||
uint16_t magic;
|
||||
uint16_t code;
|
||||
char buf[1024 - 8];
|
||||
};
|
||||
|
||||
void *usbThread(void *) {
|
||||
UsbPacket pkt;
|
||||
UsbPacket resp;
|
||||
while (true) {
|
||||
int len = read(usbFD, &pkt, sizeof(pkt));
|
||||
if (len <= 4) {
|
||||
sleep_core_us(20000);
|
||||
continue;
|
||||
}
|
||||
resp.msgcount = pkt.msgcount;
|
||||
if (pkt.magic == USB_MAGIC) {
|
||||
if (pkt.code == USB_RESTART) {
|
||||
target_reset();
|
||||
} else if (pkt.code == USB_DMESG) {
|
||||
dumpDmesg();
|
||||
}
|
||||
/*
|
||||
resp.magic = pkt.magic;
|
||||
resp.code = pkt.code;
|
||||
resp.size = 8;
|
||||
write(usbFD, &resp, sizeof(resp));
|
||||
*/
|
||||
} else {
|
||||
resp.magic = 0xffff;
|
||||
resp.size = 4;
|
||||
write(usbFD, &resp, sizeof(resp));
|
||||
}
|
||||
sleep_core_us(1000);
|
||||
}
|
||||
}
|
||||
|
||||
static void startUsb() {
|
||||
usbFD = open("/dev/lms_usbdev", O_RDWR, 0666);
|
||||
pthread_t pid;
|
||||
pthread_create(&pid, NULL, usbThread, NULL);
|
||||
pthread_detach(pid);
|
||||
}
|
||||
|
||||
static void *exitThread(void *) {
|
||||
int fd = open("/dev/lms_ui", O_RDWR, 0666);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
uint8_t *data =
|
||||
(uint8_t *)mmap(NULL, NUM_BUTTONS, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (data == MAP_FAILED) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
for (;;) {
|
||||
if (data[5])
|
||||
target_reset();
|
||||
sleep_core_us(50000);
|
||||
}
|
||||
}
|
||||
|
||||
static void startExitThread() {
|
||||
pthread_t pid;
|
||||
pthread_create(&pid, NULL, exitThread, NULL);
|
||||
pthread_detach(pid);
|
||||
}
|
||||
|
||||
void sendUsb(uint16_t code, const char *data, int len) {
|
||||
while (len > 0) {
|
||||
int sz = len;
|
||||
if (sz > 1000)
|
||||
sz = 1000;
|
||||
UsbPacket pkt = {(uint16_t)(6 + sz), 0, USB_MAGIC, code, {}};
|
||||
memcpy(pkt.buf, data, sz);
|
||||
write(usbFD, &pkt, sizeof(pkt));
|
||||
len -= sz;
|
||||
data += sz;
|
||||
}
|
||||
}
|
||||
|
||||
void sendSerial(const char *data, int len) {
|
||||
sendUsb(USB_SERIAL, data, len);
|
||||
}
|
||||
|
||||
volatile bool paniced;
|
||||
extern "C" void drawPanic(int code);
|
||||
|
||||
extern "C" void target_panic(int error_code) {
|
||||
char buf[50];
|
||||
paniced = true;
|
||||
pthread_mutex_trylock(&execMutex);
|
||||
|
||||
snprintf(buf, sizeof(buf), "\nPANIC %d\n", error_code);
|
||||
|
||||
drawPanic(error_code);
|
||||
DMESG("PANIC %d", error_code);
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
sendSerial(buf, strlen(buf));
|
||||
sleep_core_us(500 * 1000);
|
||||
}
|
||||
|
||||
target_reset();
|
||||
}
|
||||
|
||||
void startUser() {
|
||||
pthread_mutex_lock(&execMutex);
|
||||
}
|
||||
|
||||
void stopUser() {
|
||||
pthread_mutex_unlock(&execMutex);
|
||||
}
|
||||
|
||||
void sleep_core_us(uint64_t us) {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = us / 1000000;
|
||||
ts.tv_nsec = (us % 1000000) * 1000;
|
||||
while (nanosleep(&ts, &ts))
|
||||
;
|
||||
}
|
||||
|
||||
void sleep_ms(uint32_t ms) {
|
||||
stopUser();
|
||||
sleep_core_us(ms * 1000);
|
||||
startUser();
|
||||
}
|
||||
|
||||
void sleep_us(uint64_t us) {
|
||||
if (us > 50000) {
|
||||
sleep_ms(us / 1000);
|
||||
}
|
||||
sleep_core_us(us);
|
||||
}
|
||||
|
||||
uint64_t currTime() {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||
}
|
||||
|
||||
int current_time_ms() {
|
||||
return currTime() - startTime;
|
||||
}
|
||||
|
||||
void disposeThread(Thread *t) {
|
||||
if (allThreads == t) {
|
||||
allThreads = t->next;
|
||||
} else {
|
||||
for (auto tt = allThreads; tt; tt = tt->next) {
|
||||
if (tt->next == t) {
|
||||
tt->next = t->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
decr(t->act);
|
||||
decr(t->arg0);
|
||||
decr(t->data0);
|
||||
decr(t->data1);
|
||||
pthread_cond_destroy(&t->waitCond);
|
||||
delete t;
|
||||
}
|
||||
|
||||
static void runAct(Thread *thr) {
|
||||
startUser();
|
||||
pxt::runAction1(thr->act, thr->arg0);
|
||||
stopUser();
|
||||
disposeThread(thr);
|
||||
}
|
||||
|
||||
static void mainThread(Thread *) {}
|
||||
|
||||
void setupThread(Action a, TValue arg = 0, void (*runner)(Thread *) = NULL, TValue d0 = 0,
|
||||
TValue d1 = 0) {
|
||||
if (runner == NULL)
|
||||
runner = runAct;
|
||||
auto thr = new Thread();
|
||||
memset(thr, 0, sizeof(Thread));
|
||||
thr->next = allThreads;
|
||||
allThreads = thr;
|
||||
thr->act = incr(a);
|
||||
thr->arg0 = incr(arg);
|
||||
thr->data0 = incr(d0);
|
||||
thr->data1 = incr(d1);
|
||||
pthread_cond_init(&thr->waitCond, NULL);
|
||||
if (runner == mainThread) {
|
||||
thr->pid = pthread_self();
|
||||
} else {
|
||||
pthread_create(&thr->pid, NULL, (void *(*)(void *))runner, thr);
|
||||
THREAD_DBG("setup thread: %p (pid %p)", thr, thr->pid);
|
||||
pthread_detach(thr->pid);
|
||||
}
|
||||
}
|
||||
|
||||
void releaseFiber() {
|
||||
stopUser();
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
void runInParallel(Action a) {
|
||||
setupThread(a);
|
||||
}
|
||||
|
||||
static void runFor(Thread *t) {
|
||||
startUser();
|
||||
while (true) {
|
||||
pxt::runAction0(t->act);
|
||||
sleep_ms(20);
|
||||
}
|
||||
}
|
||||
|
||||
void runForever(Action a) {
|
||||
setupThread(a, 0, runFor);
|
||||
}
|
||||
|
||||
void waitForEvent(int source, int value) {
|
||||
THREAD_DBG("waitForEv: %d %d", source, value);
|
||||
auto self = pthread_self();
|
||||
for (auto t = allThreads; t; t = t->next) {
|
||||
THREAD_DBG("t: %p", t);
|
||||
if (t->pid == self) {
|
||||
pthread_mutex_lock(&eventMutex);
|
||||
t->waitSource = source;
|
||||
t->waitValue = value;
|
||||
stopUser();
|
||||
// spourious wake ups may occur they say
|
||||
while (t->waitSource) {
|
||||
pthread_cond_wait(&t->waitCond, &eventMutex);
|
||||
}
|
||||
pthread_mutex_unlock(&eventMutex);
|
||||
startUser();
|
||||
return;
|
||||
}
|
||||
}
|
||||
DMESG("current thread not registered!");
|
||||
target_panic(901);
|
||||
}
|
||||
|
||||
static void dispatchEvent(Event &e) {
|
||||
lastEvent = e;
|
||||
|
||||
auto curr = findBinding(e.source, e.value);
|
||||
if (curr)
|
||||
setupThread(curr->action, fromInt(e.value));
|
||||
|
||||
curr = findBinding(e.source, DEVICE_EVT_ANY);
|
||||
if (curr)
|
||||
setupThread(curr->action, fromInt(e.value));
|
||||
}
|
||||
|
||||
static void *evtDispatcher(void *dummy) {
|
||||
pthread_mutex_lock(&eventMutex);
|
||||
while (true) {
|
||||
pthread_cond_wait(&newEventBroadcast, &eventMutex);
|
||||
while (eventHead != NULL) {
|
||||
if (paniced)
|
||||
return 0;
|
||||
Event *ev = eventHead;
|
||||
eventHead = ev->next;
|
||||
if (eventHead == NULL)
|
||||
eventTail = NULL;
|
||||
|
||||
for (auto thr = allThreads; thr; thr = thr->next) {
|
||||
if (paniced)
|
||||
return 0;
|
||||
if (thr->waitSource == 0)
|
||||
continue;
|
||||
if (thr->waitValue != ev->value && thr->waitValue != DEVICE_EVT_ANY)
|
||||
continue;
|
||||
if (thr->waitSource == ev->source) {
|
||||
thr->waitSource = 0; // once!
|
||||
pthread_cond_broadcast(&thr->waitCond);
|
||||
} else if (thr->waitSource == DEVICE_ID_NOTIFY &&
|
||||
ev->source == DEVICE_ID_NOTIFY_ONE) {
|
||||
thr->waitSource = 0; // once!
|
||||
pthread_cond_broadcast(&thr->waitCond);
|
||||
break; // do not wake up any other threads
|
||||
}
|
||||
}
|
||||
|
||||
dispatchEvent(*ev);
|
||||
delete ev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int allocateNotifyEvent() {
|
||||
static volatile int notifyId;
|
||||
pthread_mutex_lock(&eventMutex);
|
||||
int res = ++notifyId;
|
||||
pthread_mutex_unlock(&eventMutex);
|
||||
return res;
|
||||
}
|
||||
|
||||
void raiseEvent(int id, int event) {
|
||||
auto e = mkEvent(id, event);
|
||||
pthread_mutex_lock(&eventMutex);
|
||||
if (eventTail == NULL) {
|
||||
if (eventHead != NULL)
|
||||
target_panic(902);
|
||||
eventHead = eventTail = e;
|
||||
} else {
|
||||
eventTail->next = e;
|
||||
eventTail = e;
|
||||
}
|
||||
pthread_cond_broadcast(&newEventBroadcast);
|
||||
pthread_mutex_unlock(&eventMutex);
|
||||
}
|
||||
|
||||
void registerWithDal(int id, int event, Action a, int flags) {
|
||||
// TODO support flags
|
||||
setBinding(id, event, a);
|
||||
}
|
||||
|
||||
static void runPoller(Thread *thr) {
|
||||
Action query = thr->data0;
|
||||
auto us = (uint64_t)toInt(thr->data1) * 1000;
|
||||
|
||||
// note that this is run without the user mutex held - it should not modify any state!
|
||||
TValue prev = pxt::runAction0(query);
|
||||
|
||||
startUser();
|
||||
pxt::runAction2(thr->act, prev, prev);
|
||||
stopUser();
|
||||
|
||||
while (true) {
|
||||
sleep_core_us(us);
|
||||
if (paniced)
|
||||
break;
|
||||
TValue curr = pxt::runAction0(query);
|
||||
if (curr != prev) {
|
||||
startUser();
|
||||
pxt::runAction2(thr->act, prev, curr);
|
||||
stopUser();
|
||||
if (paniced)
|
||||
break;
|
||||
decr(prev);
|
||||
prev = curr;
|
||||
}
|
||||
}
|
||||
// disposeThread(thr);
|
||||
}
|
||||
|
||||
uint32_t afterProgramPage() {
|
||||
return 0;
|
||||
}
|
||||
void dumpDmesg() {
|
||||
auto len = dmesgPtr - dmesgSerialPtr;
|
||||
if (len == 0)
|
||||
return;
|
||||
sendSerial(dmesgBuf + dmesgSerialPtr, len);
|
||||
dmesgSerialPtr = dmesgPtr;
|
||||
}
|
||||
|
||||
int lmsPid;
|
||||
void stopLMS() {
|
||||
struct dirent *ent;
|
||||
DIR *dir;
|
||||
|
||||
dir = opendir("/proc");
|
||||
if (dir == NULL)
|
||||
return;
|
||||
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
int pid = atoi(ent->d_name);
|
||||
if (!pid)
|
||||
continue;
|
||||
char namebuf[100];
|
||||
snprintf(namebuf, 1000, "/proc/%d/cmdline", pid);
|
||||
FILE *f = fopen(namebuf, "r");
|
||||
if (f) {
|
||||
fread(namebuf, 1, 99, f);
|
||||
if (strcmp(namebuf, "./lms2012") == 0) {
|
||||
lmsPid = pid;
|
||||
}
|
||||
fclose(f);
|
||||
if (lmsPid)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
lmsPid = 0; // disable SIGSTOP for now - rethink if problems with I2C (runs on a thread)
|
||||
|
||||
if (lmsPid) {
|
||||
DMESG("SIGSTOP to lmsPID=%d", lmsPid);
|
||||
if (kill(lmsPid, SIGSTOP))
|
||||
DMESG("SIGSTOP failed");
|
||||
}
|
||||
}
|
||||
|
||||
void runLMS() {
|
||||
DMESG("re-starting LMS2012");
|
||||
kill(lmsPid, SIGCONT);
|
||||
sleep_core_us(200000);
|
||||
exit(0);
|
||||
/*
|
||||
chdir("/home/root/lms2012/sys");
|
||||
for (int fd = 3; fd < 9999; ++fd)
|
||||
close(fd);
|
||||
execl("lms2012", "./lms2012");
|
||||
exit(100); // should not be reached
|
||||
*/
|
||||
}
|
||||
|
||||
void stopMotors() {
|
||||
uint8_t cmd[3] = {opOutputStop, 0x0F, 0};
|
||||
int fd = open("/dev/lms_pwm", O_RDWR);
|
||||
write(fd, cmd, 3);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void stopProgram() {
|
||||
uint8_t cmd[1] = {opOutputProgramStop};
|
||||
int fd = open("/dev/lms_pwm", O_RDWR);
|
||||
write(fd, cmd, 1);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
extern "C" void target_reset() {
|
||||
pthread_mutex_trylock(&execMutex);
|
||||
stopMotors();
|
||||
stopProgram();
|
||||
if (lmsPid)
|
||||
runLMS();
|
||||
else
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void screen_init();
|
||||
void initRuntime() {
|
||||
// daemon(1, 1);
|
||||
startTime = currTime();
|
||||
DMESG("runtime starting...");
|
||||
stopLMS();
|
||||
startUsb();
|
||||
startExitThread();
|
||||
pthread_t disp;
|
||||
pthread_create(&disp, NULL, evtDispatcher, NULL);
|
||||
pthread_detach(disp);
|
||||
setupThread(0, 0, mainThread);
|
||||
target_init();
|
||||
screen_init();
|
||||
startUser();
|
||||
}
|
||||
|
||||
static FILE *dmesgFile;
|
||||
|
||||
void dmesgRaw(const char *buf, uint32_t len) {
|
||||
if (!dmesgFile) {
|
||||
dmesgFile = fopen("/tmp/dmesg.txt", "w");
|
||||
if (!dmesgFile)
|
||||
dmesgFile = stderr;
|
||||
}
|
||||
|
||||
if (len > sizeof(dmesgBuf) / 2)
|
||||
return;
|
||||
if (dmesgPtr + len > sizeof(dmesgBuf)) {
|
||||
dmesgPtr = 0;
|
||||
dmesgSerialPtr = 0;
|
||||
}
|
||||
memcpy(dmesgBuf + dmesgPtr, buf, len);
|
||||
dmesgPtr += len;
|
||||
fwrite(buf, 1, len, dmesgFile);
|
||||
}
|
||||
|
||||
void dmesg(const char *format, ...) {
|
||||
char buf[500];
|
||||
|
||||
snprintf(buf, sizeof(buf), "[%8d] ", current_time_ms());
|
||||
dmesgRaw(buf, strlen(buf));
|
||||
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
vsnprintf(buf, sizeof(buf), format, arg);
|
||||
va_end(arg);
|
||||
dmesgRaw(buf, strlen(buf));
|
||||
dmesgRaw("\n", 1);
|
||||
|
||||
fflush(dmesgFile);
|
||||
fdatasync(fileno(dmesgFile));
|
||||
}
|
||||
} // namespace pxt
|
||||
@@ -25,20 +25,13 @@ PXT_VTABLE_CTOR(MMap) {
|
||||
}
|
||||
|
||||
void MMap::print() {
|
||||
DMESG("MMap %p len=%d fd=%d data=%p", this, length, fd, data);
|
||||
DMESG("MMap %p r=%d len=%d fd=%d data=%p", this, refcnt, length, fd, data);
|
||||
}
|
||||
|
||||
void MMap::destroy() {
|
||||
munmap(data, length);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void MMap::scan(MMap *) {}
|
||||
|
||||
unsigned MMap::gcsize(MMap *) {
|
||||
return TOWORDS(sizeof(MMap));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace control {
|
||||
@@ -46,8 +39,8 @@ namespace control {
|
||||
/** Create new file mapping in memory */
|
||||
//%
|
||||
MMap *mmap(String filename, int size, int offset) {
|
||||
DMESG("mmap %s len=%d off=%d", filename->getUTF8Data(), size, offset);
|
||||
int fd = open(filename->getUTF8Data(), O_RDWR, 0);
|
||||
DMESG("mmap %s len=%d off=%d", filename->data, size, offset);
|
||||
int fd = open(filename->data, O_RDWR, 0);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -159,7 +159,6 @@ namespace motors {
|
||||
private _accelerationTime: number;
|
||||
private _decelerationSteps: number;
|
||||
private _decelerationTime: number;
|
||||
private _inverted: boolean;
|
||||
|
||||
protected static output_types: number[] = [0x7, 0x7, 0x7, 0x7];
|
||||
|
||||
@@ -177,7 +176,6 @@ namespace motors {
|
||||
this._accelerationTime = 0;
|
||||
this._decelerationSteps = 0;
|
||||
this._decelerationTime = 0;
|
||||
this._inverted = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -227,11 +225,9 @@ namespace motors {
|
||||
//% help=motors/motor/set-inverted
|
||||
setInverted(inverted: boolean) {
|
||||
this.init();
|
||||
this._inverted = inverted;
|
||||
}
|
||||
|
||||
protected invertedFactor(): number {
|
||||
return this._inverted ? -1 : 1;
|
||||
const b = mkCmd(this._port, DAL.opOutputPolarity, 1)
|
||||
b.setNumber(NumberFormat.Int8LE, 2, inverted ? 0 : 1);
|
||||
writePWM(b)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,9 +294,8 @@ namespace motors {
|
||||
}
|
||||
|
||||
private normalizeSchedule(speed: number, step1: number, step2: number, step3: number, unit: MoveUnit): MoveSchedule {
|
||||
// motor polarity is not supported at the firmware level for sync motor operations
|
||||
const r: MoveSchedule = {
|
||||
speed: Math.clamp(-100, 100, speed | 0) * this.invertedFactor(),
|
||||
speed: Math.clamp(-100, 100, speed >> 0),
|
||||
useSteps: true,
|
||||
steps: [step1 || 0, step2 || 0, step3 || 0]
|
||||
}
|
||||
@@ -567,7 +562,6 @@ namespace motors {
|
||||
|
||||
private __init() {
|
||||
this.setOutputType(this._large);
|
||||
this.setInverted(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -747,7 +741,7 @@ namespace motors {
|
||||
//% help=motors/synced/steer
|
||||
steer(turnRatio: number, speed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) {
|
||||
this.init();
|
||||
speed = Math.clamp(-100, 100, speed >> 0) * this.invertedFactor();
|
||||
speed = Math.clamp(-100, 100, speed >> 0);
|
||||
if (!speed) {
|
||||
this.stop();
|
||||
return;
|
||||
@@ -924,3 +918,9 @@ namespace motors {
|
||||
writePWM(b)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface Buffer {
|
||||
[index: number]: number;
|
||||
// rest defined in buffer.cpp
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
#include "pxt.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <dirent.h>
|
||||
#include "ev3const.h"
|
||||
|
||||
namespace pxt {
|
||||
|
||||
static int usbFD;
|
||||
|
||||
#define USB_MAGIC 0x3d3f
|
||||
#define USB_SERIAL 1
|
||||
#define USB_RESTART 2
|
||||
#define USB_DMESG 3
|
||||
|
||||
struct UsbPacket {
|
||||
uint16_t size;
|
||||
uint16_t msgcount;
|
||||
uint16_t magic;
|
||||
uint16_t code;
|
||||
char buf[1024 - 8];
|
||||
};
|
||||
|
||||
void *usbThread(void *) {
|
||||
UsbPacket pkt;
|
||||
UsbPacket resp;
|
||||
while (true) {
|
||||
int len = read(usbFD, &pkt, sizeof(pkt));
|
||||
if (len <= 4) {
|
||||
sleep_core_us(20000);
|
||||
continue;
|
||||
}
|
||||
resp.msgcount = pkt.msgcount;
|
||||
if (pkt.magic == USB_MAGIC) {
|
||||
if (pkt.code == USB_RESTART) {
|
||||
target_reset();
|
||||
} else if (pkt.code == USB_DMESG) {
|
||||
dumpDmesg();
|
||||
}
|
||||
/*
|
||||
resp.magic = pkt.magic;
|
||||
resp.code = pkt.code;
|
||||
resp.size = 8;
|
||||
write(usbFD, &resp, sizeof(resp));
|
||||
*/
|
||||
} else {
|
||||
resp.magic = 0xffff;
|
||||
resp.size = 4;
|
||||
write(usbFD, &resp, sizeof(resp));
|
||||
}
|
||||
sleep_core_us(1000);
|
||||
}
|
||||
}
|
||||
|
||||
static void startUsb() {
|
||||
usbFD = open("/dev/lms_usbdev", O_RDWR, 0666);
|
||||
pthread_t pid;
|
||||
pthread_create(&pid, NULL, usbThread, NULL);
|
||||
pthread_detach(pid);
|
||||
}
|
||||
|
||||
static void *exitThread(void *) {
|
||||
int fd = open("/dev/lms_ui", O_RDWR, 0666);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
uint8_t *data =
|
||||
(uint8_t *)mmap(NULL, NUM_BUTTONS, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (data == MAP_FAILED) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
for (;;) {
|
||||
if (data[5])
|
||||
target_reset();
|
||||
sleep_core_us(50000);
|
||||
}
|
||||
}
|
||||
|
||||
static void startExitThread() {
|
||||
pthread_t pid;
|
||||
pthread_create(&pid, NULL, exitThread, NULL);
|
||||
pthread_detach(pid);
|
||||
}
|
||||
|
||||
void sendUsb(uint16_t code, const char *data, int len) {
|
||||
while (len > 0) {
|
||||
int sz = len;
|
||||
if (sz > 1000)
|
||||
sz = 1000;
|
||||
UsbPacket pkt = {(uint16_t)(6 + sz), 0, USB_MAGIC, code, {}};
|
||||
memcpy(pkt.buf, data, sz);
|
||||
write(usbFD, &pkt, sizeof(pkt));
|
||||
len -= sz;
|
||||
data += sz;
|
||||
}
|
||||
}
|
||||
|
||||
void sendSerial(const char *data, int len) {
|
||||
sendUsb(USB_SERIAL, data, len);
|
||||
}
|
||||
|
||||
int lmsPid;
|
||||
void stopLMS() {
|
||||
struct dirent *ent;
|
||||
DIR *dir;
|
||||
|
||||
dir = opendir("/proc");
|
||||
if (dir == NULL)
|
||||
return;
|
||||
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
int pid = atoi(ent->d_name);
|
||||
if (!pid)
|
||||
continue;
|
||||
char namebuf[100];
|
||||
snprintf(namebuf, 100, "/proc/%d/cmdline", pid);
|
||||
FILE *f = fopen(namebuf, "r");
|
||||
if (f) {
|
||||
fread(namebuf, 1, 99, f);
|
||||
if (strcmp(namebuf, "./lms2012") == 0) {
|
||||
lmsPid = pid;
|
||||
}
|
||||
fclose(f);
|
||||
if (lmsPid)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
lmsPid = 0; // disable SIGSTOP for now - rethink if problems with I2C (runs on a thread)
|
||||
|
||||
if (lmsPid) {
|
||||
DMESG("SIGSTOP to lmsPID=%d", lmsPid);
|
||||
if (kill(lmsPid, SIGSTOP))
|
||||
DMESG("SIGSTOP failed");
|
||||
}
|
||||
}
|
||||
|
||||
void runLMS() {
|
||||
DMESG("re-starting LMS2012");
|
||||
kill(lmsPid, SIGCONT);
|
||||
sleep_core_us(200000);
|
||||
exit(0);
|
||||
/*
|
||||
chdir("/home/root/lms2012/sys");
|
||||
for (int fd = 3; fd < 9999; ++fd)
|
||||
close(fd);
|
||||
execl("lms2012", "./lms2012");
|
||||
exit(100); // should not be reached
|
||||
*/
|
||||
}
|
||||
|
||||
void stopMotors() {
|
||||
uint8_t cmd[3] = {opOutputStop, 0x0F, 0};
|
||||
int fd = open("/dev/lms_pwm", O_RDWR);
|
||||
write(fd, cmd, 3);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void stopProgram() {
|
||||
uint8_t cmd[1] = {opOutputProgramStop};
|
||||
int fd = open("/dev/lms_pwm", O_RDWR);
|
||||
write(fd, cmd, 1);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
extern "C" void target_reset() {
|
||||
tryLockUser();
|
||||
stopMotors();
|
||||
stopProgram();
|
||||
if (lmsPid)
|
||||
runLMS();
|
||||
else
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void target_exit() {
|
||||
target_reset();
|
||||
}
|
||||
|
||||
|
||||
void target_startup() {
|
||||
stopLMS();
|
||||
startUsb();
|
||||
startExitThread();
|
||||
}
|
||||
|
||||
void initKeys() {}
|
||||
|
||||
static const char *progPath = "/mnt/ramdisk/prjs/BrkProg_SAVE";
|
||||
|
||||
// These are disabled except when building File_manager.pdf
|
||||
// %
|
||||
void deletePrjFile(String filename) {
|
||||
const char *d = filename->getUTF8Data();
|
||||
if (strlen(d) > 500 || strchr(d, '/'))
|
||||
return;
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof(buf), "%s/%s", progPath, d);
|
||||
unlink(buf);
|
||||
}
|
||||
|
||||
// %
|
||||
RefCollection *listPrjFiles() {
|
||||
auto res = Array_::mk();
|
||||
registerGCObj(res);
|
||||
|
||||
auto dp = opendir(progPath);
|
||||
|
||||
for (;;) {
|
||||
dirent *ep = dp ? readdir(dp) : NULL;
|
||||
if (!ep)
|
||||
break;
|
||||
if (ep->d_name[0] == '.')
|
||||
continue;
|
||||
auto str = mkString(ep->d_name, -1);
|
||||
registerGCObj(str);
|
||||
res->head.push((TValue)str);
|
||||
unregisterGCObj(str);
|
||||
}
|
||||
if (dp)
|
||||
closedir(dp);
|
||||
unregisterGCObj(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +1 @@
|
||||
#define PXT_GC_THREAD_LIST 1
|
||||
|
||||
#define PXT_IN_ISR() false
|
||||
// leave empty
|
||||
@@ -11,7 +11,6 @@ int allocateNotifyEvent();
|
||||
void sleep_core_us(uint64_t us);
|
||||
void startUser();
|
||||
void stopUser();
|
||||
int tryLockUser();
|
||||
|
||||
class Button;
|
||||
typedef Button *Button_;
|
||||
@@ -28,13 +27,9 @@ class MMap : public RefObject {
|
||||
MMap();
|
||||
void destroy();
|
||||
void print();
|
||||
|
||||
static void scan(MMap *);
|
||||
static unsigned gcsize(MMap *);
|
||||
};
|
||||
|
||||
extern volatile bool paniced;
|
||||
void target_exit();
|
||||
|
||||
// Buffer, Sound, and Image share representation.
|
||||
typedef Buffer Sound;
|
||||
|
||||
@@ -26,19 +26,11 @@
|
||||
"icons.jres",
|
||||
"ns.ts",
|
||||
"platform.h",
|
||||
"platform.cpp",
|
||||
"dmesg.cpp",
|
||||
"integrator.ts"
|
||||
],
|
||||
"testFiles": [
|
||||
"test.ts"
|
||||
],
|
||||
"dalDTS": {
|
||||
"includeDirs": [
|
||||
"pxtapp"
|
||||
]
|
||||
},
|
||||
"additionalFilePath": "../../node_modules/pxt-common-packages/libs/core---linux",
|
||||
"npmDependencies": {},
|
||||
"public": true,
|
||||
"dependencies": {
|
||||
|
||||
16
libs/core/pxtcore.h
Normal file
16
libs/core/pxtcore.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef __PXTCORE_H
|
||||
#define __PXTCORE_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace pxt {
|
||||
void dmesg(const char *fmt, ...);
|
||||
#define DMESG pxt::dmesg
|
||||
}
|
||||
|
||||
static inline void itoa(int v, char *dst) {
|
||||
|
||||
snprintf(dst, 30, "%d", v);
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -85,9 +85,10 @@ void updateScreen(Image_ img) {
|
||||
lastImg = img;
|
||||
}
|
||||
|
||||
if (lastImg && mappedFrameBuffer != MAP_FAILED) {
|
||||
if (lastImg && lastImg->isDirty() && mappedFrameBuffer != MAP_FAILED) {
|
||||
if (lastImg->bpp() != 1 || lastImg->width() != LCD_WIDTH || lastImg->height() != LCD_HEIGHT)
|
||||
target_panic(906);
|
||||
lastImg->clearDirty();
|
||||
bitBufferToFrameBufferSwap(lastImg->pix(), mappedFrameBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ struct hci_dev_list_req {
|
||||
hci_dev_req dev_req[2];
|
||||
};
|
||||
|
||||
static uint64_t bt_addr() {
|
||||
uint64_t res = -1;
|
||||
static uint32_t bt_addr() {
|
||||
uint32_t res = -1;
|
||||
|
||||
int fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
|
||||
if (fd < 0) {
|
||||
@@ -50,8 +50,11 @@ static uint64_t bt_addr() {
|
||||
goto done;
|
||||
}
|
||||
|
||||
res = 0;
|
||||
memcpy(&res, di.bdaddr, 6);
|
||||
memcpy(&res, di.bdaddr, 4);
|
||||
res *= 0x1000193;
|
||||
res += di.bdaddr[4];
|
||||
res *= 0x1000193;
|
||||
res += di.bdaddr[5];
|
||||
|
||||
done:
|
||||
close(fd);
|
||||
@@ -60,10 +63,14 @@ done:
|
||||
|
||||
namespace pxt {
|
||||
|
||||
uint64_t getLongSerialNumber() {
|
||||
static uint64_t serial;
|
||||
if (serial == 0)
|
||||
serial = bt_addr();
|
||||
int getSerialNumber() {
|
||||
static int serial;
|
||||
|
||||
if (serial != 0)
|
||||
return serial;
|
||||
|
||||
serial = bt_addr() & 0x7fffffff;
|
||||
|
||||
return serial;
|
||||
}
|
||||
|
||||
|
||||
6
libs/core/shims.d.ts
vendored
6
libs/core/shims.d.ts
vendored
@@ -68,12 +68,6 @@ declare namespace control {
|
||||
/** Write data to DMESG debugging buffer. */
|
||||
//% shim=control::dmesg
|
||||
function dmesg(s: string): void;
|
||||
|
||||
/**
|
||||
* Determines if the USB has been enumerated.
|
||||
*/
|
||||
//% shim=control::isUSBInitialized
|
||||
function isUSBInitialized(): boolean;
|
||||
}
|
||||
declare namespace serial {
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace brick {
|
||||
/**
|
||||
* Exits the program to the main menu. (in the simulator restarts it)
|
||||
*/
|
||||
//% blockId=loopstop block="exit program"
|
||||
//% help=reference/brick/exit-program
|
||||
//% weight=10
|
||||
//% blockGap=8
|
||||
//% group="Buttons"
|
||||
export function exitProgram() {
|
||||
control.reset();
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace console._screen {
|
||||
lines = [];
|
||||
console.addListener(log);
|
||||
brick.buttonUp.onEvent(ButtonEvent.Bumped, () => scroll(-3))
|
||||
brick.buttonDown.onEvent(ButtonEvent.Bumped, () => scroll(3))
|
||||
brick.buttonDown.onEvent(ButtonEvent.Bumped, () => scroll(3))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace console._screen {
|
||||
printLog();
|
||||
}
|
||||
|
||||
function log(priority: ConsolePriority, msg: string): void {
|
||||
function log(msg: string): void {
|
||||
lines.push(msg);
|
||||
if (lines.length + 5 > maxLines) {
|
||||
lines.splice(0, maxLines - lines.length);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
//% color="#68C3E2" weight=100 icon="\uf106"
|
||||
//% groups='["Buttons", "Screen", "Power"]'
|
||||
//% groups='["Buttons", "Screen", "Battery"]'
|
||||
//% labelLineWidth=60
|
||||
namespace brick {
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
"name": "ev3",
|
||||
"description": "The EV3 library",
|
||||
"files": [
|
||||
"README.md",
|
||||
"README.md",
|
||||
"ns.ts",
|
||||
"brick.ts",
|
||||
"startup.ts",
|
||||
"images.jres",
|
||||
"images.ts",
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
// This is the last thing executed before user code
|
||||
console.addListener(function(priority: ConsolePriority, msg: string) {
|
||||
console.addListener(function(msg: string) {
|
||||
control.dmesg(msg.substr(0, msg.length - 1))
|
||||
})
|
||||
// boot sequence
|
||||
brick.showBoot();
|
||||
// pulse green, play startup sound, turn off light
|
||||
brick.setStatusLight(StatusLight.GreenPulse);
|
||||
// We pause for 100ms to give time to read sensor values, so they work in on_start block
|
||||
pause(400)
|
||||
// and we're ready
|
||||
brick.setStatusLight(StatusLight.Off);
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
namespace image {
|
||||
/**
|
||||
* Get the screen image
|
||||
*/
|
||||
//%
|
||||
export function screenImage(): Image {
|
||||
return screen;
|
||||
}
|
||||
}
|
||||
14
libs/screen/shims.d.ts
vendored
14
libs/screen/shims.d.ts
vendored
@@ -15,7 +15,7 @@ declare interface Image {
|
||||
height: int32;
|
||||
|
||||
/**
|
||||
* True if the image is monochromatic (black and white)
|
||||
* True iff the image is monochromatic (black and white)
|
||||
*/
|
||||
//% property shim=ImageMethods::isMono
|
||||
isMono: boolean;
|
||||
@@ -45,18 +45,6 @@ declare interface Image {
|
||||
//% shim=ImageMethods::fill
|
||||
fill(c: int32): void;
|
||||
|
||||
/**
|
||||
* Copy row(s) of pixel from image to buffer (8 bit per pixel).
|
||||
*/
|
||||
//% shim=ImageMethods::getRows
|
||||
getRows(x: int32, dst: Buffer): void;
|
||||
|
||||
/**
|
||||
* Copy row(s) of pixel from buffer to image.
|
||||
*/
|
||||
//% shim=ImageMethods::setRows
|
||||
setRows(x: int32, src: Buffer): void;
|
||||
|
||||
/**
|
||||
* Return a copy of the current image
|
||||
*/
|
||||
|
||||
@@ -129,8 +129,8 @@ namespace brick {
|
||||
|
||||
screenMode = ScreenMode.Ports;
|
||||
renderPorts();
|
||||
control.runInParallel(function () {
|
||||
while (screenMode == ScreenMode.Ports) {
|
||||
control.runInParallel(function() {
|
||||
while(screenMode == ScreenMode.Ports) {
|
||||
renderPorts();
|
||||
pause(50);
|
||||
}
|
||||
@@ -140,18 +140,8 @@ namespace brick {
|
||||
function renderPorts() {
|
||||
const col = 44;
|
||||
const lineHeight8 = image.font8.charHeight + 2;
|
||||
const h = screen.height;
|
||||
|
||||
clearScreen();
|
||||
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
const x = i * col + 2;
|
||||
screen.print("ABCD"[i], x, 1 * lineHeight8, 1, image.font8)
|
||||
screen.print((i + 1).toString(), x, h - lineHeight8, 1, image.font8)
|
||||
}
|
||||
screen.drawLine(0, 5 * lineHeight8, screen.width, 5 * lineHeight8, 1);
|
||||
screen.drawLine(0, h - 5 * lineHeight8, screen.width, h - 5 * lineHeight8, 1)
|
||||
|
||||
function scale(x: number) {
|
||||
if (Math.abs(x) >= 5000) {
|
||||
const k = Math.floor(x / 1000);
|
||||
@@ -165,38 +155,27 @@ namespace brick {
|
||||
const datas = motors.getAllMotorData();
|
||||
for (let i = 0; i < datas.length; ++i) {
|
||||
const data = datas[i];
|
||||
const x = i * col + 2;
|
||||
if (!data.actualSpeed && !data.count) continue;
|
||||
screen.print(`${scale(data.actualSpeed)}%`, x, 3 * lineHeight8, 1, image.font8)
|
||||
screen.print(`${scale(data.count)}>`, x, 4 * lineHeight8, 1, image.font8)
|
||||
const x = i * col;
|
||||
screen.print("ABCD"[i], x + 2, 1 * lineHeight8, 1, image.font8)
|
||||
screen.print(`${scale(data.actualSpeed)}%`, x + 2, 3 * lineHeight8, 1, image.font8)
|
||||
screen.print(`${scale(data.count)}>`, x + 2, 4 * lineHeight8, 1, image.font8)
|
||||
}
|
||||
screen.drawLine(0, 5 * lineHeight8, screen.width, 5 * lineHeight8, 1);
|
||||
|
||||
// sensors
|
||||
const sis = sensors.internal.getActiveSensors();
|
||||
const h = screen.height;
|
||||
screen.drawLine(0, h - 5 * lineHeight8, screen.width, h - 5 * lineHeight8, 1)
|
||||
for (let i = 0; i < sis.length; ++i) {
|
||||
const si = sis[i];
|
||||
const x = (si.port() - 1) * col + 2;
|
||||
const x = (si.port() - 1) * col;
|
||||
const inf = si._info();
|
||||
if (inf)
|
||||
screen.print(inf, x, h - 2 * lineHeight8, 1, inf.length > 4 ? image.font5 : image.font8);
|
||||
screen.print(si.port() + "", x, h - 4 * lineHeight8, 1, image.font8)
|
||||
screen.print(inf, x, h - 2 * lineHeight8, 1, inf.length > 4 ? image.font5 : image.font8);
|
||||
}
|
||||
}
|
||||
|
||||
export function showBoot() {
|
||||
// pulse green, play startup sound, turn off light
|
||||
brick.setStatusLight(StatusLight.GreenPulse);
|
||||
// We pause for 100ms to give time to read sensor values, so they work in on_start block
|
||||
pause(400)
|
||||
// and we're ready
|
||||
brick.setStatusLight(StatusLight.Off);
|
||||
// always show port by default if no UI is set
|
||||
control.runInParallel(function () {
|
||||
// show ports if nothing is has been shown
|
||||
if (screenMode != ScreenMode.None) return;
|
||||
showPorts();
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* An image
|
||||
* @param image the image
|
||||
|
||||
16
package.json
16
package.json
@@ -1,13 +1,12 @@
|
||||
{
|
||||
"name": "pxt-ev3",
|
||||
"version": "1.4.17",
|
||||
"version": "1.2.22",
|
||||
"description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode",
|
||||
"private": false,
|
||||
"keywords": [
|
||||
"JavaScript",
|
||||
"education",
|
||||
"LEGO",
|
||||
"EV3",
|
||||
"lego",
|
||||
"pxt",
|
||||
"MakeCode",
|
||||
"Microsoft"
|
||||
@@ -33,20 +32,15 @@
|
||||
],
|
||||
"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/react-dom": "16.0.3",
|
||||
"@types/web-bluetooth": "0.0.4"
|
||||
"webfonts-generator": "^0.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"pxt-common-packages": "6.16.37",
|
||||
"pxt-core": "5.30.19"
|
||||
"pxt-common-packages": "0.23.61",
|
||||
"pxt-core": "4.0.11"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node node_modules/pxt-core/built/pxt.js travis"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
],
|
||||
"simulator": {
|
||||
"autoRun": true,
|
||||
"autoRunLight": false,
|
||||
"streams": true,
|
||||
"aspectRatio": 0.5,
|
||||
"parts": false,
|
||||
"enableTrace": true,
|
||||
@@ -37,10 +37,7 @@
|
||||
"publishing": true,
|
||||
"importing": true,
|
||||
"preferredPackages": [],
|
||||
"githubPackages": true,
|
||||
"cloudProviders": {
|
||||
"github": {}
|
||||
}
|
||||
"githubPackages": true
|
||||
},
|
||||
"compile": {
|
||||
"isNative": true,
|
||||
@@ -53,16 +50,15 @@
|
||||
"flashCodeAlign": 256,
|
||||
"floatingPoint": true,
|
||||
"taggedInts": true,
|
||||
"stackAlign": 2,
|
||||
"gc": true
|
||||
"stackAlign": 2
|
||||
},
|
||||
"serial": {
|
||||
"vendorId": "0x0694",
|
||||
"productId": "0x0005",
|
||||
"rawHID": true,
|
||||
"useEditor": true,
|
||||
"log": true
|
||||
},
|
||||
"vendorId": "0x0694",
|
||||
"productId": "0x0005",
|
||||
"rawHID": true,
|
||||
"useEditor": true,
|
||||
"log": true
|
||||
},
|
||||
"runtime": {
|
||||
"mathBlocks": true,
|
||||
"loopsBlocks": true,
|
||||
@@ -76,9 +72,7 @@
|
||||
"onStartColor": "#58AB41",
|
||||
"pauseUntilBlock": {
|
||||
"category": "loops"
|
||||
},
|
||||
"bannedCategories": [
|
||||
]
|
||||
}
|
||||
},
|
||||
"compileService": {
|
||||
"buildEngine": "dockermake",
|
||||
@@ -88,7 +82,7 @@
|
||||
"appTheme": {
|
||||
"accentColor": "#0089BF",
|
||||
"logoWide": true,
|
||||
"logoUrl": "https://education.lego.com/",
|
||||
"logoUrl": "https://education.lego.com/",
|
||||
"logo": "./static/lego_education_logo.png",
|
||||
"docsLogo": "./static/lego_education_logo.png",
|
||||
"portraitLogo": "./static/lego_education_logo.png",
|
||||
@@ -157,12 +151,6 @@
|
||||
"usbHelp": [],
|
||||
"extendEditor": true,
|
||||
"extendFieldEditors": true,
|
||||
"scriptManager": true,
|
||||
"importExtensionFiles": true,
|
||||
"experiments": [
|
||||
"python",
|
||||
"alwaysGithubItemBlocks"
|
||||
],
|
||||
"disableBlockIcons": true,
|
||||
"blocklyOptions": {
|
||||
"grid": {
|
||||
@@ -198,12 +186,7 @@
|
||||
"editor.background": "#f9f9f9"
|
||||
},
|
||||
"fileNameExclusiveFilter": "[^a-zA-Z0-9]",
|
||||
"qrCode": true,
|
||||
"shareFinishedTutorials": true,
|
||||
"nameProjectFirst": true,
|
||||
"alwaysGithubItem": true,
|
||||
"enableTrace": true
|
||||
},
|
||||
"ignoreDocsErrors": true,
|
||||
"uploadDocs": true
|
||||
}
|
||||
"ignoreDocsErrors": true
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
//% shim=pxt::listPrjFiles
|
||||
function getPrjs() {
|
||||
let programs = [
|
||||
"pxt",
|
||||
"my amazing robot",
|
||||
]
|
||||
for (let i = 1; i < 6; ++i)
|
||||
programs.push("Untitled-" + i)
|
||||
return programs
|
||||
}
|
||||
|
||||
//% shim=pxt::deletePrjFile
|
||||
function delPrj(fn: string) {
|
||||
return
|
||||
}
|
||||
|
||||
const programs = getPrjs()
|
||||
.filter(s => s.substr(s.length - 4, 4) == ".rbf")
|
||||
.map(s => s.substr(0, s.length - 4))
|
||||
.filter(s => s != "File_manager")
|
||||
|
||||
programs.push("")
|
||||
programs.push("Cancel")
|
||||
programs.push("Delete 0 files")
|
||||
|
||||
let todel: boolean[] = []
|
||||
let scrollTop = 0
|
||||
let cursor = 0
|
||||
let confirm = false
|
||||
function showMenu() {
|
||||
if (cursor < scrollTop + 2)
|
||||
scrollTop = cursor - 2
|
||||
else if (cursor > scrollTop + 11)
|
||||
scrollTop = cursor - 11
|
||||
if (scrollTop < 0)
|
||||
scrollTop = 0
|
||||
let num = 0
|
||||
for (let i = 0; i < todel.length; ++i)
|
||||
if (todel[i]) num++
|
||||
programs[programs.length - 1] =
|
||||
confirm ? "Enter to confirm" : "Delete " + num + " file(s)"
|
||||
|
||||
brick.clearScreen()
|
||||
|
||||
const h = brick.lineHeight()
|
||||
for (let i = 0; i < 13; ++i) {
|
||||
const y = i * h
|
||||
const idx = scrollTop + i
|
||||
const fg = idx == cursor ? 0 : 1
|
||||
const bg = idx == cursor ? 1 : 0
|
||||
// screen.fillRect(0, y, screen.width, h, bg);
|
||||
let text = (idx == cursor ? ">" : " ")
|
||||
+ (todel[idx] ? "*" : " ")
|
||||
+ " "
|
||||
+ (programs[scrollTop + i] || "")
|
||||
screen.print(text, 0, y, fg, brick.font);
|
||||
}
|
||||
}
|
||||
function move(d: number) {
|
||||
confirm = false
|
||||
const nc = cursor + d
|
||||
if (0 <= nc && nc < programs.length)
|
||||
cursor = nc
|
||||
showMenu()
|
||||
}
|
||||
brick.buttonDown.onEvent(ButtonEvent.Pressed, () => move(1))
|
||||
brick.buttonUp.onEvent(ButtonEvent.Pressed, () => move(-1))
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
if (cursor < programs.length - 3) {
|
||||
todel[cursor] = !todel[cursor]
|
||||
move(1)
|
||||
} else if (cursor == programs.length - 3) {
|
||||
// nothing
|
||||
} else if (cursor == programs.length - 2) {
|
||||
control.reset()
|
||||
} else if (cursor == programs.length - 1) {
|
||||
if (todel.every(x => !x))
|
||||
return
|
||||
if (confirm) {
|
||||
brick.clearScreen()
|
||||
brick.showString("deleting...", 6)
|
||||
for (let i = 0; i < todel.length; ++i) {
|
||||
if (todel[i]) {
|
||||
delPrj(programs[i] + ".elf")
|
||||
delPrj(programs[i] + ".rbf")
|
||||
}
|
||||
}
|
||||
pause(1000)
|
||||
control.reset()
|
||||
} else {
|
||||
confirm = true
|
||||
showMenu()
|
||||
}
|
||||
}
|
||||
})
|
||||
showMenu()
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
namespace pxsim {
|
||||
|
||||
export class EV3Board extends CoreBoard {
|
||||
viewHost: visuals.BoardHost;
|
||||
view: SVGSVGElement;
|
||||
|
||||
outputState: EV3OutputState;
|
||||
@@ -84,8 +83,7 @@ namespace pxsim {
|
||||
highContrast: msg.highContrast,
|
||||
light: msg.light
|
||||
};
|
||||
this.viewHost = new visuals.BoardHost(pxsim.visuals.mkBoardView({
|
||||
boardDef,
|
||||
const viewHost = new visuals.BoardHost(pxsim.visuals.mkBoardView({
|
||||
visual: boardDef.visual,
|
||||
highContrast: msg.highContrast,
|
||||
light: msg.light
|
||||
@@ -93,7 +91,7 @@ namespace pxsim {
|
||||
|
||||
document.body.innerHTML = ""; // clear children
|
||||
document.body.className = msg.light ? "light" : "";
|
||||
document.body.appendChild(this.view = this.viewHost.getView() as SVGSVGElement);
|
||||
document.body.appendChild(this.view = viewHost.getView() as SVGSVGElement);
|
||||
|
||||
this.inputNodes = [];
|
||||
this.outputNodes = [];
|
||||
@@ -104,8 +102,8 @@ namespace pxsim {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
screenshotAsync(width?: number): Promise<ImageData> {
|
||||
return this.viewHost.screenshotAsync(width);
|
||||
screenshot(): string {
|
||||
return svg.toDataUri(new XMLSerializer().serializeToString(this.view));
|
||||
}
|
||||
|
||||
getBrickNode() {
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace pxsim {
|
||||
private angle: number = 0;
|
||||
private tacho: number = 0;
|
||||
private speed: number = 0;
|
||||
private polarity: number = 1; // -1, 1 or -1
|
||||
|
||||
private started: boolean;
|
||||
private speedCmd: DAL;
|
||||
@@ -30,7 +31,7 @@ namespace pxsim {
|
||||
}
|
||||
|
||||
getSpeed() {
|
||||
return Math.round(this.speed);
|
||||
return Math.round(this.speed * (!this._synchedMotor && this.polarity == 0 ? -1 : 1));
|
||||
}
|
||||
|
||||
getAngle() {
|
||||
@@ -81,6 +82,16 @@ namespace pxsim {
|
||||
return this.id == NodeType.LargeMotor;
|
||||
}
|
||||
|
||||
setPolarity(polarity: number) {
|
||||
// Either 1 or 255 (reverse)
|
||||
/*
|
||||
-1 : Motor will run backward
|
||||
0 : Motor will run opposite direction
|
||||
1 : Motor will run forward
|
||||
*/
|
||||
this.polarity = polarity;
|
||||
}
|
||||
|
||||
reset() {
|
||||
// not sure what reset does...
|
||||
}
|
||||
|
||||
@@ -119,7 +119,11 @@ namespace pxsim {
|
||||
return 2;
|
||||
}
|
||||
case DAL.opOutputPolarity: {
|
||||
console.error("opOutputPolarity not supported");
|
||||
// reverse
|
||||
const port = buf.data[1];
|
||||
const polarity = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int8LE, 2);
|
||||
const motors = ev3board().getMotor(port);
|
||||
motors.forEach(motor => motor.setPolarity(polarity));
|
||||
return 2;
|
||||
}
|
||||
case DAL.opOutputSetType: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
namespace pxsim.music {
|
||||
export function fromWAV(buf: RefBuffer) {
|
||||
return buf
|
||||
return incr(buf)
|
||||
}
|
||||
|
||||
export function stopAllSounds() {
|
||||
@@ -13,7 +13,7 @@ namespace pxsim.SoundMethods {
|
||||
let audio: HTMLAudioElement;
|
||||
|
||||
export function buffer(buf: RefBuffer) {
|
||||
return buf
|
||||
return incr(buf)
|
||||
}
|
||||
|
||||
export function play(buf: RefBuffer) {
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace pxsim.visuals {
|
||||
const dalBoard = board();
|
||||
dalBoard.updateSubscribers.push(() => this.updateState());
|
||||
if (props && props.wireframe)
|
||||
U.addClass(this.element, "sim-wireframe");
|
||||
svg.addClass(this.element, "sim-wireframe");
|
||||
|
||||
if (props && props.theme)
|
||||
this.updateTheme();
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace pxsim.visuals {
|
||||
protected buildDomCore() {
|
||||
// Setup buttons
|
||||
this.buttons = this.btnids.map(n => this.content.getElementById(this.normalizeId(n)) as SVGElement);
|
||||
this.buttons.forEach(b => U.addClass(b, "sim-button"));
|
||||
this.buttons.forEach(b => svg.addClass(b, "sim-button"));
|
||||
|
||||
this.light = this.content.getElementById(this.normalizeId(BrickView.EV3_LIGHT_ID)) as SVGElement;
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
"Design Engineering": "design-engineering",
|
||||
"Coding": "coding",
|
||||
"Maker": "maker",
|
||||
"Tutorial Videos": "videos"
|
||||
"Videos": "videos"
|
||||
},
|
||||
"electronManifest": {
|
||||
"latest": "v1.2.26"
|
||||
"latest": "v1.1.22"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,6 @@
|
||||
/*******************************
|
||||
Add your custom CSS here
|
||||
*******************************/
|
||||
.simframe.ui.embed {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
|
||||
/* Open Sans font */
|
||||
@font-face {
|
||||
|
||||
Reference in New Issue
Block a user