Compare commits
332 Commits
Author | SHA1 | Date | |
---|---|---|---|
f4727f12c9 | |||
a36cb65aa5 | |||
3b16e59ee1 | |||
f2c43c74ac | |||
1c4c93dc60 | |||
d73847bfba | |||
4e46682489 | |||
ab7aa00747 | |||
2bebb6056d | |||
22046c417c | |||
dc8afa6d45 | |||
22e2ab5ad9 | |||
f365726a8e | |||
e329b3bd2e | |||
d7b709e97b | |||
9714ec46e9 | |||
20ef54f565 | |||
554df0bce9 | |||
6c89dddef6 | |||
23f91895f7 | |||
3f83cda087 | |||
7e79635413 | |||
56e1cf91ac | |||
f9f96f33f0 | |||
0b33073be1 | |||
65594842fc | |||
c6ed665f84 | |||
79462deb24 | |||
5c05f3e241 | |||
4f7dd75fbe | |||
338e507b51 | |||
601231a5dc | |||
f0850336e5 | |||
a6b2187ec5 | |||
28ae4f4230 | |||
09933b6a8d | |||
45bb6e7cb3 | |||
33c234a87e | |||
e9aa343d67 | |||
d83039430c | |||
5b2e877aef | |||
c5b28f5b8e | |||
e765021bf9 | |||
dbcd9e535c | |||
cff88d67ad | |||
3f241e8bc9 | |||
69c3d2d249 | |||
bc04d30595 | |||
63a26835b1 | |||
79113115e0 | |||
573ed7f6f2 | |||
61da1032d6 | |||
36d455c693 | |||
42c766b6d7 | |||
6f00384891 | |||
8440f7c763 | |||
8a8e864f99 | |||
7a3402b782 | |||
5e9a5b29f4 | |||
aff9d1ee60 | |||
8add7e8efb | |||
e7dfd0531b | |||
d2b1f70ce2 | |||
fbf7513c44 | |||
e9bdc26d15 | |||
52fafe9359 | |||
971dca6c96 | |||
a761c27b19 | |||
a062a85c7f | |||
a9865a731a | |||
ba4095ac9c | |||
8606a00701 | |||
bf57ba2902 | |||
4cd61cd96a | |||
c4139a862f | |||
ca3cd1de22 | |||
d7f22bc8e6 | |||
28b28d0b52 | |||
0ee2b285c0 | |||
d5cb085264 | |||
c055a5d329 | |||
8fe8b78f4c | |||
f627f125c0 | |||
7d3254477a | |||
3149ed4c1d | |||
baeafcdebe | |||
12754acc54 | |||
329baaf9a4 | |||
47efcfb41f | |||
e2d1b8a55c | |||
579eb29ce3 | |||
ada9560642 | |||
7b352b3a58 | |||
a5d5836ea2 | |||
57dc26a127 | |||
3e37b03808 | |||
d035713786 | |||
6e4a71b2f4 | |||
0b4dd534ab | |||
ed07f0baad | |||
004d34b5df | |||
aa380baf1c | |||
5123a962d9 | |||
7dcd770508 | |||
ead4d32446 | |||
a51a14022a | |||
05098252ed | |||
8e74965964 | |||
63913c2182 | |||
c55716e148 | |||
dd94442555 | |||
56f6a2fa56 | |||
4ca9df141c | |||
a29e06abce | |||
43e4d06fd9 | |||
3c8027425a | |||
3f66870688 | |||
1f32a4851e | |||
478b1c84de | |||
20ac14fdf6 | |||
c805d67cf6 | |||
943c2e7716 | |||
298a37e576 | |||
327d52014c | |||
6a5cfae5ff | |||
64ebb5c8c3 | |||
bb97b57b01 | |||
534e3723d2 | |||
ad6ef04b1f | |||
2c09b7794f | |||
4941ce1694 | |||
aa6a965f59 | |||
1831c30050 | |||
df5989760c | |||
6a7f65894c | |||
f56e9369dd | |||
e23c5e019f | |||
1aa08f63fe | |||
8ef94d2854 | |||
797474063d | |||
b76622542b | |||
6a1415b3e1 | |||
2d09aef287 | |||
3ce1fa9b6e | |||
155bbb25f7 | |||
5fb3da5a77 | |||
5b682cd8d9 | |||
4755f0953c | |||
bdcd299805 | |||
3e23fe4814 | |||
3782d26e64 | |||
84a29eec65 | |||
299efaf0f2 | |||
33c60b467b | |||
81f74f07b2 | |||
583b08df28 | |||
01f80b67bc | |||
a890d2a357 | |||
0d1b91afc3 | |||
5c0d37d718 | |||
c81e56613e | |||
4cc7215d35 | |||
8751d2aaa1 | |||
af91622dda | |||
45d4caf595 | |||
a8e1d2a86c | |||
5099b11823 | |||
37e0307698 | |||
1b15eefa5a | |||
a4eccaf4f9 | |||
5981863e3f | |||
9ac7a4c522 | |||
9f1c3ee13c | |||
8b9c3d71d5 | |||
6d726b7499 | |||
b5da5afd1d | |||
420898e98c | |||
f6b392356c | |||
f4896f8d7c | |||
4dbd691146 | |||
2742dba0c4 | |||
5bea47a094 | |||
835a4b5cf0 | |||
055704b3ef | |||
60107aa7ce | |||
787ab021a7 | |||
f56a70f502 | |||
4ec6749ee6 | |||
8413b61397 | |||
ecbb970983 | |||
36e6570296 | |||
92c63b615a | |||
f71267c988 | |||
38fc0f8099 | |||
8c7238eab3 | |||
2baca30184 | |||
ac56979142 | |||
ff72858c42 | |||
deac587164 | |||
7a0a2fbd0a | |||
79c32097b5 | |||
26c20d9fc3 | |||
fe826a508a | |||
62d2140d24 | |||
499d619faf | |||
c178e58260 | |||
d242501fe6 | |||
37a438735d | |||
b862cfc4ec | |||
31002ae1a8 | |||
e8a3a2f676 | |||
e6baf8c35e | |||
b72ff9fe4f | |||
58f79ea617 | |||
ed6d343992 | |||
92b46d5c7b | |||
9cf7f08ae2 | |||
3b05b8f2f6 | |||
774d614d79 | |||
545f715eeb | |||
45b480c6dd | |||
7cc93507d9 | |||
80d3f67e6c | |||
dfbea2719b | |||
ce5da6bf80 | |||
d8d2129685 | |||
5dd37a1494 | |||
6cfe39dac3 | |||
660b22b398 | |||
b9a24a4542 | |||
af5bf6e04e | |||
ecc71a3295 | |||
0834402b18 | |||
8edd8ac73a | |||
1207a91a7f | |||
727490668c | |||
f068b3d204 | |||
205a486e58 | |||
f3bfd41a75 | |||
8d5c5daaaf | |||
83cfe8f534 | |||
9378e5e90c | |||
8617f0f3b4 | |||
0ecf3dc2b4 | |||
76005841fa | |||
7bf00ff139 | |||
82e34d852c | |||
7cd8ee1e23 | |||
a91a87b628 | |||
9d71f46e78 | |||
ccf405e64c | |||
c0a75d1845 | |||
e65a521bd4 | |||
1f203269ff | |||
18feea45bb | |||
597f0c895b | |||
5f21789d90 | |||
64826db4aa | |||
b150ee873f | |||
34effcefc6 | |||
68be2384d9 | |||
2629192bdb | |||
67b5afd73a | |||
5d8193301c | |||
adf21fee6f | |||
20f3e1d24e | |||
bf8f38fe38 | |||
3e3b8ebec5 | |||
8faeeffecf | |||
343968cf09 | |||
ca92f787e8 | |||
49a67e73be | |||
11af897c3d | |||
08cd04b2c8 | |||
c1656cf441 | |||
8f3c585588 | |||
dd181e4178 | |||
ff3689e92d | |||
fffcf0f809 | |||
240162370e | |||
98238caffb | |||
f55977a51d | |||
91938f156a | |||
eb01245cce | |||
17cbea9989 | |||
22c03dfd7a | |||
cf3e8684d5 | |||
cd0b2a646f | |||
d7528c09e3 | |||
e055484492 | |||
947d69da48 | |||
07822c47a3 | |||
25d6746b7e | |||
7cb85ff459 | |||
73d18c8d39 | |||
74b6d99ab1 | |||
491ff29e40 | |||
d1db619c8d | |||
733996f83e | |||
4a624cb365 | |||
637ea17f8e | |||
f8d6bd280e | |||
b91de5bad2 | |||
d7c3433bb2 | |||
43456e9a53 | |||
081244218f | |||
6ae39f192b | |||
ed5263f248 | |||
f1ee861eb4 | |||
2ce2fd95ba | |||
741f94ce6c | |||
4b7e415ae7 | |||
3efbb4fbde | |||
4d9450dd06 | |||
910870e46f | |||
b664df4208 | |||
c660277a23 | |||
0416d88d59 | |||
4f822e3cda | |||
20d4e473ff | |||
e45190922e | |||
1df118fa19 | |||
8ba27ccc2d | |||
ff646d32b5 | |||
75d99b324c | |||
ece91d980a | |||
a6a9f25e86 | |||
cc5330bf3d | |||
4a9e1466e6 | |||
fa947036f0 | |||
0b0884a7eb | |||
d5b2a21d16 |
14
.gitignore
vendored
@ -1,14 +1,20 @@
|
||||
node_modules
|
||||
yotta_modules
|
||||
yotta_targets
|
||||
pxt_modules
|
||||
built
|
||||
typings
|
||||
tmp
|
||||
temp
|
||||
projects/**
|
||||
win10/app/bin
|
||||
win10/app/bld
|
||||
win10/*.opendb
|
||||
clients/win10/app/AppPackages
|
||||
clients/win10/app/BundlePackages
|
||||
clients/win10/app/BundleArtifacts
|
||||
clients/win10/app/bin
|
||||
clients/win10/app/bld
|
||||
clients/win10/*.opendb
|
||||
clients/**/bin/**
|
||||
clients/**/obj/**
|
||||
|
||||
*.user
|
||||
*.sw?
|
||||
@ -16,4 +22,4 @@ win10/*.opendb
|
||||
*.tgz
|
||||
*.db
|
||||
*.suo
|
||||
*.log
|
||||
*.log
|
||||
|
@ -4,8 +4,12 @@ node_js:
|
||||
script:
|
||||
- "node node_modules/pxt-core/built/pxt.js travis"
|
||||
- "(cd libs/lang-test0; node ../../node_modules/pxt-core/built/pxt.js run)"
|
||||
- "(cd libs/lang-test1; node ../../node_modules/pxt-core/built/pxt.js run)"
|
||||
- "(cd libs/lang-test0; node ../../node_modules/pxt-core/built/pxt.js test)"
|
||||
- "(cd libs/lang-test1; node ../../node_modules/pxt-core/built/pxt.js test)"
|
||||
- "node node_modules/pxt-core/built/pxt.js testdir tests"
|
||||
- "node node_modules/pxt-core/built/pxt.js uploaddoc"
|
||||
- "(cd libs/hello; node ../../node_modules/pxt-core/built/pxt.js testconv ../../testconv.json)"
|
||||
- "(cd libs/hello; node ../../node_modules/pxt-core/built/pxt.js testconv https://az851932.vo.msecnd.net/files/td-converter-tests-v0.json)"
|
||||
sudo: false
|
||||
notifications:
|
||||
email:
|
||||
@ -14,4 +18,5 @@ cache:
|
||||
directories:
|
||||
- node_modules
|
||||
- built/cache
|
||||
- libs/hello/built/cache
|
||||
|
||||
|
41
README.md
@ -3,17 +3,25 @@
|
||||
This target allow to program a [BBC micro:bit](https://www.microbit.co.uk/) using
|
||||
PXT ([Microsoft Programming Experience Toolkit](https://github.com/Microsoft/pxt)).
|
||||
|
||||
* [Try it live](https://m.pxt.io)
|
||||
* [Try it live](https://codethemicrobit.com)
|
||||
|
||||
[](https://travis-ci.org/Microsoft/pxt-microbit)
|
||||
|
||||
## Local server
|
||||
|
||||
The local server allows to run the editor and the documentation from your computer.
|
||||
|
||||
### Setup
|
||||
|
||||
The following commands are a 1-time setup after synching the repo on your machine.
|
||||
|
||||
* install the PXT command line
|
||||
* if not yet installed, install [Node.js 4.4.5 or higher](https://nodejs.org/en/download/)
|
||||
* [clone this repo](https://help.github.com/articles/cloning-a-repository/) to your computer and go in the project folder
|
||||
```
|
||||
git clone https://github.com/microsoft/pxt-microbit
|
||||
cd pxt-microbit
|
||||
```
|
||||
* install the PXT command line (add ``sudo`` for Mac/Linux shells).
|
||||
```
|
||||
npm install -g pxt
|
||||
```
|
||||
@ -36,7 +44,9 @@ If you need modify the `.cpp` files, turn on yotta compilation with the ``-yt``
|
||||
pxt serve -yt
|
||||
```
|
||||
|
||||
To make sure you're running the latest tools, run (add ``sudo`` for Mac/Linux shells)
|
||||
## Updates
|
||||
|
||||
To update your PXT version and make sure you're running the latest tools, run (add ``sudo`` for Mac/Linux shells)
|
||||
```
|
||||
pxt update
|
||||
```
|
||||
@ -46,9 +56,30 @@ More instructions at https://github.com/Microsoft/pxt#running-a-target-from-loca
|
||||
## Universal Windows App
|
||||
|
||||
The Windows 10 app is a [Universal Windows Hosted Web App](https://microsoftedge.github.io/WebAppsDocs/en-US/win10/CreateHWA.htm)
|
||||
that wraps ``m.pxt.io`` and provides additional features.
|
||||
that wraps ``codethemicrobit.com`` and provides additional features.
|
||||
|
||||
### Building
|
||||
|
||||
* Install Visual Studio 2015 Update 2 or higher. Make sure the Windows 10 templates are installed.
|
||||
* open the ``win10/app.sln`` solution and launch the ``m.pxt.io`` project.
|
||||
* open the ``win10/app.sln`` solution and launch the ``codethemicrobit`` project.
|
||||
|
||||
## Testing
|
||||
|
||||
The build automatically runs the following:
|
||||
|
||||
* make sure the built-in packages compile
|
||||
* `pxt run` in `libs/lang-test*` - this will run the test in command line runner;
|
||||
there is a number of asserts in both of these
|
||||
* `pxt testdir` in `tests` - this makes sure all the files compile and generates .hex files
|
||||
* run the TD->TS converter on a number of test scripts from `microbit.co.uk` and make sure the results compile
|
||||
|
||||
To test something on the device:
|
||||
|
||||
* do a `pxt deploy` in `libs/lang-test*` - they should show `1` or `2` on the screen (and not unhappy face)
|
||||
* run `pxt testdir` in `tests` and deploy some of the hex files from `tests/built`
|
||||
|
||||
The `lang-test0` source comes from the `pxt-core` package. It's also tested with `pxt run` there.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
26
clients/chrome/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
# microbit-chrome
|
||||
Prototype chrome addon that exposes the micro:bit's serial output to webpages.
|
||||
* watch the [demo video](https://vimeo.com/146207766)
|
||||
|
||||
# Installation
|
||||
See [developer.chrome.com](https://developer.chrome.com/extensions/getstarted#unpacked)
|
||||
for instructions on how to install the local version into your chrome browser.
|
||||
|
||||
# Requirements
|
||||
* Chrome 48 or later.
|
||||
|
||||
# Sample page
|
||||
The `demo.html` webpage goes along with the
|
||||
https://github.com/Microsoft/microbit-touchdevelop/blob/master/examples/tcs34725.cpp
|
||||
program. Run `http-server` from this directory, then visit
|
||||
http://localhost:8080/demo.html
|
||||
(keep in mind that pages served from `file://` cannot open ports).
|
||||
|
||||
# Building
|
||||
|
||||
Open a command prompt and run the following commands.
|
||||
|
||||
````
|
||||
npm install
|
||||
typings update
|
||||
````
|
68
clients/chrome/background.js
Normal file
@ -0,0 +1,68 @@
|
||||
///<reference path='typings/browser.d.ts'/>
|
||||
var connections = [];
|
||||
// A list of "ports", i.e. connected clients (such as web pages). Multiple web
|
||||
// pages can connect to our service: they all receive the same data.
|
||||
var ports = [];
|
||||
function byPath(path) {
|
||||
return connections.filter(function (x) { return x.path == path; });
|
||||
}
|
||||
function byId(id) {
|
||||
return connections.filter(function (x) { return x.id == id; });
|
||||
}
|
||||
function onReceive(data, id) {
|
||||
if (ports.length == 0)
|
||||
return;
|
||||
var view = new DataView(data);
|
||||
var decoder = new TextDecoder("utf-8");
|
||||
var decodedString = decoder.decode(view);
|
||||
ports.forEach(function (port) { return port.postMessage({
|
||||
type: "serial",
|
||||
data: decodedString,
|
||||
id: id
|
||||
}); });
|
||||
}
|
||||
function findNewDevices() {
|
||||
chrome.serial.getDevices(function (serialPorts) {
|
||||
serialPorts.forEach(function (serialPort) {
|
||||
if (byPath(serialPort.path).length == 0 &&
|
||||
serialPort.displayName == "mbed Serial Port") {
|
||||
chrome.serial.connect(serialPort.path, { bitrate: 115200 }, function (info) {
|
||||
// In case the [connect] operation takes more than five seconds...
|
||||
if (info && byPath(serialPort.path).length == 0)
|
||||
connections.push({
|
||||
id: info.connectionId,
|
||||
path: serialPort.path
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
function main() {
|
||||
// Register new clients in the [ports] global variable.
|
||||
chrome.runtime.onConnectExternal.addListener(function (port) {
|
||||
if (/^(micro:bit|touchdevelop|yelm|pxt|codemicrobit|codethemicrobit)$/.test(port.name)) {
|
||||
ports.push(port);
|
||||
port.onDisconnect.addListener(function () {
|
||||
ports = ports.filter(function (x) { return x != port; });
|
||||
});
|
||||
}
|
||||
});
|
||||
// When receiving data for one of the connections that we're tracking, forward
|
||||
// it to all connected clients.
|
||||
chrome.serial.onReceive.addListener(function (info) {
|
||||
if (byId(info.connectionId).length > 0)
|
||||
onReceive(info.data, info.connectionId);
|
||||
});
|
||||
// When it looks like we've been disconnected, drop the corresponding
|
||||
// connection object from the [connections] global variable.
|
||||
chrome.serial.onReceiveError.addListener(function (info) {
|
||||
if (info.error == "system_error" || info.error == "disconnected" || info.error == "device_lost")
|
||||
connections = connections.filter(function (x) { return x.id != info.connectionId; });
|
||||
});
|
||||
// Probe serial connections at regular intervals. In case we find an mbed port
|
||||
// we haven't yet connected to, connect to it.
|
||||
setInterval(findNewDevices, 5000);
|
||||
findNewDevices();
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", main);
|
92
clients/chrome/background.ts
Normal file
@ -0,0 +1,92 @@
|
||||
// A list of: {
|
||||
// id: number;
|
||||
// path: string;
|
||||
// } where [id] is the [connectionId] (internal to Chrome) and [path] is the
|
||||
// OS' name for the device (e.g. "COM4").
|
||||
interface Connection {
|
||||
id: string;
|
||||
path: string;
|
||||
}
|
||||
let connections: Connection[] = [];
|
||||
|
||||
// A list of "ports", i.e. connected clients (such as web pages). Multiple web
|
||||
// pages can connect to our service: they all receive the same data.
|
||||
let ports = [];
|
||||
|
||||
interface Message {
|
||||
type: string;
|
||||
data: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
function byPath(path: string): Connection[] {
|
||||
return connections.filter((x) => x.path == path);
|
||||
}
|
||||
|
||||
function byId(id: string): Connection[] {
|
||||
return connections.filter((x) => x.id == id);
|
||||
}
|
||||
|
||||
function onReceive(data, id: string) {
|
||||
if (ports.length == 0) return;
|
||||
|
||||
let view = new DataView(data);
|
||||
let decoder = new TextDecoder("utf-8");
|
||||
let decodedString = decoder.decode(view);
|
||||
ports.forEach(port => port.postMessage(<Message>{
|
||||
type: "serial",
|
||||
data: decodedString,
|
||||
id: id,
|
||||
}));
|
||||
}
|
||||
|
||||
function findNewDevices() {
|
||||
chrome.serial.getDevices(function (serialPorts) {
|
||||
serialPorts.forEach(function (serialPort) {
|
||||
if (byPath(serialPort.path).length == 0 &&
|
||||
serialPort.displayName == "mbed Serial Port") {
|
||||
chrome.serial.connect(serialPort.path, { bitrate: 115200 }, function (info) {
|
||||
// In case the [connect] operation takes more than five seconds...
|
||||
if (info && byPath(serialPort.path).length == 0)
|
||||
connections.push({
|
||||
id: info.connectionId,
|
||||
path: serialPort.path
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function main() {
|
||||
// Register new clients in the [ports] global variable.
|
||||
chrome.runtime.onConnectExternal.addListener(function (port) {
|
||||
if (/^(micro:bit|touchdevelop|yelm|pxt|codemicrobit|codethemicrobit)$/.test(port.name)) {
|
||||
ports.push(port);
|
||||
port.onDisconnect.addListener(function () {
|
||||
ports = ports.filter(function (x) { return x != port });
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// When receiving data for one of the connections that we're tracking, forward
|
||||
// it to all connected clients.
|
||||
chrome.serial.onReceive.addListener(function (info) {
|
||||
if (byId(info.connectionId).length > 0)
|
||||
onReceive(info.data, info.connectionId);
|
||||
});
|
||||
|
||||
// When it looks like we've been disconnected, drop the corresponding
|
||||
// connection object from the [connections] global variable.
|
||||
chrome.serial.onReceiveError.addListener(function (info) {
|
||||
if (info.error == "system_error" || info.error == "disconnected" || info.error == "device_lost")
|
||||
connections = connections.filter((x) => x.id != info.connectionId);
|
||||
});
|
||||
|
||||
// Probe serial connections at regular intervals. In case we find an mbed port
|
||||
// we haven't yet connected to, connect to it.
|
||||
setInterval(findNewDevices, 5000);
|
||||
findNewDevices();
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", main);
|
BIN
clients/chrome/logo128.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
clients/chrome/logo48.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
30
clients/chrome/manifest.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"app": {
|
||||
"background": {
|
||||
"scripts": [ "background.js" ]
|
||||
}
|
||||
},
|
||||
|
||||
"manifest_version": 2,
|
||||
"name": "code the micro:bit",
|
||||
"version": "0.6.0",
|
||||
"author": "Microsoft Corporation",
|
||||
"short_name": "code the micro:bit",
|
||||
|
||||
"description": "Extension for https://codethemicrobit.com.",
|
||||
"homepage_url": "https://codethemicrobit.com",
|
||||
"offline_enabled": "true",
|
||||
"icons": {
|
||||
"48": "logo48.png",
|
||||
"128": "logo128.png"
|
||||
},
|
||||
|
||||
"permissions": [
|
||||
"serial",
|
||||
"usb"
|
||||
],
|
||||
|
||||
"externally_connectable": {
|
||||
"matches": [ "*://localhost/*", "https://codethemicrobit.com/*", "https://*.codethemicrobit.com/*" ]
|
||||
}
|
||||
}
|
BIN
clients/chrome/screenshot.png
Normal file
After Width: | Height: | Size: 138 KiB |
7
clients/chrome/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"compiler-options": {
|
||||
"target": "ES5",
|
||||
"module": "amd",
|
||||
"sourceMap": false
|
||||
}
|
||||
}
|
@ -20,22 +20,18 @@
|
||||
<ProjectConfiguration Include="Release|AnyCPU">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>AnyCPU</Platform>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x86">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x86</Platform>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
48
clients/win10/app/codethemicrobitapp.sln
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25123.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "codethemicrobitapp", "codethemicrobitapp.jsproj", "{39122940-AB16-4CD4-A0CE-79A3EB863ECF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x64.Build.0 = Debug|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x86.Build.0 = Debug|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|ARM.Build.0 = Release|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x64.ActiveCfg = Release|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x64.Build.0 = Release|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x64.Deploy.0 = Release|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x86.ActiveCfg = Release|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x86.Build.0 = Release|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x86.Deploy.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
@ -14,13 +14,13 @@
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
<Applications>
|
||||
<Application Id="App" StartPage="https://m.pxt.io/">
|
||||
<Application Id="App" StartPage="https://codethemicrobit.com">
|
||||
<uap:ApplicationContentUriRules>
|
||||
<uap:Rule Match="https://m.pxt.io/" Type="include" WindowsRuntimeAccess="all" />
|
||||
<uap:Rule Match="https://codemicrobit.com/" Type="include" WindowsRuntimeAccess="all" />
|
||||
<uap:Rule Match="https://codethemicrobit.com/" Type="include" WindowsRuntimeAccess="all" />
|
||||
</uap:ApplicationContentUriRules>
|
||||
<uap:VisualElements DisplayName="codethemicrobit" Description="Code editors for the BBC micro:bit" BackgroundColor="white" Square150x150Logo="images\Square150x150Logo.png" Square44x44Logo="images\Square44x44Logo.png">
|
||||
<uap:VisualElements DisplayName="code the micro:bit" Description="A code editor for the BBC micro:bit with Blocks or Javascript." BackgroundColor="white" Square150x150Logo="images\Square150x150Logo.png" Square44x44Logo="images\Square44x44Logo.png">
|
||||
<uap:DefaultTile Wide310x150Logo="images\Wide310x150Logo.png" ShortName="code the micro:bit">
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="images\splashscreen.png" />
|
BIN
clients/win10/store/desktopblocks1366x768.png
Normal file
After Width: | Height: | Size: 172 KiB |
BIN
clients/win10/store/desktopjavascript1366x768.png
Normal file
After Width: | Height: | Size: 121 KiB |
BIN
clients/win10/store/mobileblocks480x800.png
Normal file
After Width: | Height: | Size: 54 KiB |
66
clients/winuploader/CodeTheMicroBit.sln
Normal file
@ -0,0 +1,66 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25123.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeTheMicrobit", "Microbit.Uploader\CodeTheMicrobit.csproj", "{7DC6CA45-FD75-44BC-805E-708C812CD4BF}"
|
||||
EndProject
|
||||
Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "codethemicrobitapp", "..\win10\app\codethemicrobitapp.jsproj", "{39122940-AB16-4CD4-A0CE-79A3EB863ECF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7DC6CA45-FD75-44BC-805E-708C812CD4BF}.Release|x86.Build.0 = Release|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x64.Build.0 = Debug|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x86.Build.0 = Debug|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|ARM.Build.0 = Release|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x64.ActiveCfg = Release|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x64.Build.0 = Release|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x64.Deploy.0 = Release|x64
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x86.ActiveCfg = Release|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x86.Build.0 = Release|x86
|
||||
{39122940-AB16-4CD4-A0CE-79A3EB863ECF}.Release|x86.Deploy.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
7
clients/winuploader/Microbit.Uploader/App.config
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0"/>
|
||||
<supportedRuntime version="v2.0.50727"/>
|
||||
</startup>
|
||||
</configuration>
|
123
clients/winuploader/Microbit.Uploader/CodeTheMicrobit.csproj
Normal file
@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{7DC6CA45-FD75-44BC-805E-708C812CD4BF}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Microsoft.MicroBit</RootNamespace>
|
||||
<AssemblyName>CodeTheMicrobit</AssemblyName>
|
||||
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<RunCodeAnalysis>true</RunCodeAnalysis>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>
|
||||
</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<DelaySign>false</DelaySign>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup />
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualBasic" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Settings.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Settings.Designer.cs">
|
||||
<DependentUpon>Settings.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="GlobalSuppressions.cs" />
|
||||
<Compile Include="KnownFolders.cs" />
|
||||
<Compile Include="LicenseDialog.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="LicenseDialog.Designer.cs">
|
||||
<DependentUpon>LicenseDialog.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="MainForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="MainForm.Designer.cs">
|
||||
<DependentUpon>MainForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SingleInstanceAppHelper.cs" />
|
||||
<Compile Include="SingleInstanceAppStarter.cs" />
|
||||
<EmbeddedResource Include="LicenseDialog.resx">
|
||||
<DependentUpon>LicenseDialog.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="MainForm.resx">
|
||||
<DependentUpon>MainForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Settings.resx">
|
||||
<DependentUpon>Settings.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="MSFT_logo_png.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="Resources\MSR-LA - 2576.rtf" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="favicon.ico" />
|
||||
<EmbeddedResource Include="microbit.red.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
BIN
clients/winuploader/Microbit.Uploader/GlobalSuppressions.cs
Normal file
33
clients/winuploader/Microbit.Uploader/KnownFolders.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Management;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
/// <summary>
|
||||
/// Class containing methods to retrieve specific file system paths.
|
||||
/// </summary>
|
||||
internal static class KnownFoldersNativeMethods
|
||||
{
|
||||
[SecurityCritical]
|
||||
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
|
||||
public static string GetDownloadPath()
|
||||
{
|
||||
IntPtr outPath;
|
||||
int result = SHGetKnownFolderPath(new Guid("{374DE290-123F-4565-9164-39C4925E467B}"), 0x00004000, new IntPtr(0), out outPath);
|
||||
if (result >= 0)
|
||||
return Marshal.PtrToStringUni(outPath);
|
||||
else return null;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule")]
|
||||
[DllImport("Shell32.dll")]
|
||||
[SecurityCritical]
|
||||
private static extern int SHGetKnownFolderPath(
|
||||
[MarshalAs(UnmanagedType.LPStruct)]Guid rfid, uint dwFlags, IntPtr hToken,
|
||||
out IntPtr ppszPath);
|
||||
}
|
||||
|
||||
}
|
93
clients/winuploader/Microbit.Uploader/LicenseDialog.Designer.cs
generated
Normal file
@ -0,0 +1,93 @@
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
partial class LicenseDialog
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.textBox = new System.Windows.Forms.RichTextBox();
|
||||
this.acceptButton = new System.Windows.Forms.Button();
|
||||
this.exitButton = new System.Windows.Forms.Button();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// textBox
|
||||
//
|
||||
this.textBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.textBox.Location = new System.Drawing.Point(13, 13);
|
||||
this.textBox.Name = "textBox";
|
||||
this.textBox.ReadOnly = true;
|
||||
this.textBox.Size = new System.Drawing.Size(465, 438);
|
||||
this.textBox.TabIndex = 0;
|
||||
this.textBox.Text = "";
|
||||
//
|
||||
// acceptButton
|
||||
//
|
||||
this.acceptButton.Location = new System.Drawing.Point(322, 457);
|
||||
this.acceptButton.Name = "acceptButton";
|
||||
this.acceptButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.acceptButton.TabIndex = 1;
|
||||
this.acceptButton.Text = "Accept";
|
||||
this.acceptButton.UseVisualStyleBackColor = true;
|
||||
this.acceptButton.Click += new System.EventHandler(this.acceptButton_Click);
|
||||
//
|
||||
// exitButton
|
||||
//
|
||||
this.exitButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.exitButton.Location = new System.Drawing.Point(403, 457);
|
||||
this.exitButton.Name = "exitButton";
|
||||
this.exitButton.Size = new System.Drawing.Size(75, 23);
|
||||
this.exitButton.TabIndex = 2;
|
||||
this.exitButton.Text = "Exit";
|
||||
this.exitButton.UseVisualStyleBackColor = true;
|
||||
this.exitButton.Click += new System.EventHandler(this.exitButton_Click);
|
||||
//
|
||||
// LicenseDialog
|
||||
//
|
||||
this.AcceptButton = this.acceptButton;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.exitButton;
|
||||
this.ClientSize = new System.Drawing.Size(490, 492);
|
||||
this.ControlBox = false;
|
||||
this.Controls.Add(this.exitButton);
|
||||
this.Controls.Add(this.acceptButton);
|
||||
this.Controls.Add(this.textBox);
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "LicenseDialog";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "code the micro:bit terms of use";
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.RichTextBox textBox;
|
||||
private System.Windows.Forms.Button acceptButton;
|
||||
private System.Windows.Forms.Button exitButton;
|
||||
}
|
||||
}
|
32
clients/winuploader/Microbit.Uploader/LicenseDialog.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using Microsoft.MicroBit.Properties;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
public partial class LicenseDialog : Form
|
||||
{
|
||||
public LicenseDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.textBox.Rtf = Resources.MSR_LA___2576;
|
||||
}
|
||||
|
||||
private void acceptButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.DialogResult = DialogResult.Yes;
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void exitButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.DialogResult = DialogResult.No;
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
120
clients/winuploader/Microbit.Uploader/LicenseDialog.resx
Normal file
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
BIN
clients/winuploader/Microbit.Uploader/MSFT_logo_png.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
173
clients/winuploader/Microbit.Uploader/MainForm.Designer.cs
generated
Normal file
@ -0,0 +1,173 @@
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
partial class MainForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
||||
this.statusLabel = new System.Windows.Forms.Label();
|
||||
this.backgroundPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.trayIcon = new System.Windows.Forms.NotifyIcon(this.components);
|
||||
this.versionLabel = new System.Windows.Forms.LinkLabel();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.SettingsLabel = new System.Windows.Forms.LinkLabel();
|
||||
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
||||
this.linkLabel1 = new System.Windows.Forms.LinkLabel();
|
||||
((System.ComponentModel.ISupportInitialize)(this.backgroundPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// statusLabel
|
||||
//
|
||||
this.statusLabel.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.statusLabel.Font = new System.Drawing.Font("Consolas", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.statusLabel.Location = new System.Drawing.Point(11, 30);
|
||||
this.statusLabel.Name = "statusLabel";
|
||||
this.statusLabel.Size = new System.Drawing.Size(364, 23);
|
||||
this.statusLabel.TabIndex = 1;
|
||||
this.statusLabel.Text = "loading...";
|
||||
//
|
||||
// backgroundPictureBox
|
||||
//
|
||||
this.backgroundPictureBox.BackColor = System.Drawing.Color.White;
|
||||
this.backgroundPictureBox.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.backgroundPictureBox.Image = global::Microsoft.MicroBit.Properties.Resources.MSFT_logo_png;
|
||||
this.backgroundPictureBox.InitialImage = null;
|
||||
this.backgroundPictureBox.Location = new System.Drawing.Point(226, 91);
|
||||
this.backgroundPictureBox.Name = "backgroundPictureBox";
|
||||
this.backgroundPictureBox.Size = new System.Drawing.Size(149, 52);
|
||||
this.backgroundPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.backgroundPictureBox.TabIndex = 0;
|
||||
this.backgroundPictureBox.TabStop = false;
|
||||
this.backgroundPictureBox.Click += new System.EventHandler(this.backgroundPictureBox_Click);
|
||||
//
|
||||
// trayIcon
|
||||
//
|
||||
this.trayIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("trayIcon.Icon")));
|
||||
this.trayIcon.Visible = true;
|
||||
this.trayIcon.Click += new System.EventHandler(this.trayIcon_Click);
|
||||
//
|
||||
// versionLabel
|
||||
//
|
||||
this.versionLabel.AutoSize = true;
|
||||
this.versionLabel.Location = new System.Drawing.Point(12, 121);
|
||||
this.versionLabel.Name = "versionLabel";
|
||||
this.versionLabel.Size = new System.Drawing.Size(28, 13);
|
||||
this.versionLabel.TabIndex = 2;
|
||||
this.versionLabel.TabStop = true;
|
||||
this.versionLabel.Text = "v0.9";
|
||||
this.versionLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.versionLabel_LinkClicked);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label1.Location = new System.Drawing.Point(12, 103);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(169, 15);
|
||||
this.label1.TabIndex = 3;
|
||||
this.label1.Text = "Automatic upload of .hex files.";
|
||||
//
|
||||
// SettingsLabel
|
||||
//
|
||||
this.SettingsLabel.AutoSize = true;
|
||||
this.SettingsLabel.Location = new System.Drawing.Point(151, 121);
|
||||
this.SettingsLabel.Name = "SettingsLabel";
|
||||
this.SettingsLabel.Size = new System.Drawing.Size(43, 13);
|
||||
this.SettingsLabel.TabIndex = 4;
|
||||
this.SettingsLabel.TabStop = true;
|
||||
this.SettingsLabel.Text = "settings";
|
||||
this.SettingsLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.SettingsLabel_LinkClicked);
|
||||
//
|
||||
// pictureBox1
|
||||
//
|
||||
this.pictureBox1.BackColor = System.Drawing.Color.White;
|
||||
this.pictureBox1.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.pictureBox1.Image = global::Microsoft.MicroBit.Properties.Resources.microbit_red;
|
||||
this.pictureBox1.InitialImage = null;
|
||||
this.pictureBox1.Location = new System.Drawing.Point(226, 6);
|
||||
this.pictureBox1.Name = "pictureBox1";
|
||||
this.pictureBox1.Size = new System.Drawing.Size(149, 79);
|
||||
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.pictureBox1.TabIndex = 5;
|
||||
this.pictureBox1.TabStop = false;
|
||||
this.pictureBox1.Click += new System.EventHandler(this.pictureBox1_Click);
|
||||
//
|
||||
// linkLabel1
|
||||
//
|
||||
this.linkLabel1.AutoSize = true;
|
||||
this.linkLabel1.Location = new System.Drawing.Point(62, 121);
|
||||
this.linkLabel1.Name = "linkLabel1";
|
||||
this.linkLabel1.Size = new System.Drawing.Size(60, 13);
|
||||
this.linkLabel1.TabIndex = 6;
|
||||
this.linkLabel1.TabStop = true;
|
||||
this.linkLabel1.Text = "open editor";
|
||||
this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.White;
|
||||
this.ClientSize = new System.Drawing.Size(388, 143);
|
||||
this.Controls.Add(this.linkLabel1);
|
||||
this.Controls.Add(this.pictureBox1);
|
||||
this.Controls.Add(this.SettingsLabel);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.versionLabel);
|
||||
this.Controls.Add(this.statusLabel);
|
||||
this.Controls.Add(this.backgroundPictureBox);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MaximizeBox = false;
|
||||
this.Name = "MainForm";
|
||||
this.ShowInTaskbar = false;
|
||||
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "code the micro:bit";
|
||||
this.Load += new System.EventHandler(this.MainForm_Load);
|
||||
((System.ComponentModel.ISupportInitialize)(this.backgroundPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.PictureBox backgroundPictureBox;
|
||||
private System.Windows.Forms.Label statusLabel;
|
||||
private System.Windows.Forms.NotifyIcon trayIcon;
|
||||
private System.Windows.Forms.LinkLabel versionLabel;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.LinkLabel SettingsLabel;
|
||||
private System.Windows.Forms.PictureBox pictureBox1;
|
||||
private System.Windows.Forms.LinkLabel linkLabel1;
|
||||
}
|
||||
}
|
||||
|
267
clients/winuploader/Microbit.Uploader/MainForm.cs
Normal file
@ -0,0 +1,267 @@
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Security;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
internal partial class MainForm : Form
|
||||
{
|
||||
FileSystemWatcher watcher;
|
||||
private string customcopypath = "";
|
||||
|
||||
public MainForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
var v = typeof(MainForm).Assembly.GetName().Version;
|
||||
this.versionLabel.Text = "v" + v.Major + "." + v.Minor;
|
||||
}
|
||||
|
||||
private void MainForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
this.initializeFileWatch();
|
||||
customcopypath = (string)Application.UserAppDataRegistry.GetValue("CustomDirectory", "");
|
||||
this.openEditor();
|
||||
}
|
||||
|
||||
private void openEditor()
|
||||
{
|
||||
// lanch editor
|
||||
try { Process.Start("https://codethemicrobit.com"); } catch (Exception) { }
|
||||
}
|
||||
|
||||
private void initializeFileWatch()
|
||||
{
|
||||
if (!checkTOU()) return;
|
||||
|
||||
var downloads = KnownFoldersNativeMethods.GetDownloadPath();
|
||||
if (downloads == null)
|
||||
{
|
||||
this.updateStatus("oops, can't find the `Downloads` folder");
|
||||
return;
|
||||
}
|
||||
|
||||
this.watcher = new FileSystemWatcher(downloads);
|
||||
this.watcher.Renamed += (sender, e) => this.handleFileEvent(e);
|
||||
this.watcher.Created += (sender, e) => this.handleFileEvent(e);
|
||||
this.watcher.EnableRaisingEvents = true;
|
||||
|
||||
this.waitingForHexFileStatus();
|
||||
}
|
||||
|
||||
private void waitingForHexFileStatus()
|
||||
{
|
||||
this.updateStatus("waiting for .hex file...");
|
||||
this.trayIcon.ShowBalloonTip(3000, "ready...", "waiting for .hex file...", ToolTipIcon.None);
|
||||
}
|
||||
|
||||
static bool checkTOU()
|
||||
{
|
||||
var v = (int)Application.UserAppDataRegistry.GetValue("TermOfUse", 0);
|
||||
if (v != 1)
|
||||
{
|
||||
using (var f = new LicenseDialog())
|
||||
{
|
||||
var r = f.ShowDialog();
|
||||
if (r != DialogResult.Yes)
|
||||
{
|
||||
Application.Exit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Application.UserAppDataRegistry.SetValue("TermOfUse", 1, RegistryValueKind.DWord);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
delegate void Callback();
|
||||
|
||||
private void updateStatus(string value)
|
||||
{
|
||||
Callback a = (Callback)(() =>
|
||||
{
|
||||
this.statusLabel.Text = value;
|
||||
this.trayIcon.Text = value;
|
||||
});
|
||||
this.Invoke(a);
|
||||
}
|
||||
|
||||
void handleFileEvent(FileSystemEventArgs e)
|
||||
{
|
||||
this.handleFile(e.FullPath);
|
||||
}
|
||||
|
||||
volatile int copying;
|
||||
void handleFile(string fullPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
// In case this is data-url download, at least Chrome will not rename file, but instead write to it
|
||||
// directly. This mean we may catch it in the act. Let's leave it some time to finish writing.
|
||||
Thread.Sleep(500);
|
||||
|
||||
var info = new System.IO.FileInfo(fullPath);
|
||||
Trace.WriteLine("download: " + info.FullName);
|
||||
|
||||
if (info.Extension != ".hex") return;
|
||||
|
||||
var infoName = info.Name;
|
||||
Trace.WriteLine("download name: " + info.Name);
|
||||
if (!infoName.StartsWith("microbit-", StringComparison.OrdinalIgnoreCase)) return;
|
||||
if (info.Name.EndsWith(".uploaded.hex", StringComparison.OrdinalIgnoreCase)) return;
|
||||
if (info.Length > 1000000) return; // make sure we don't try to copy large files
|
||||
|
||||
|
||||
// already copying?
|
||||
if (Interlocked.Exchange(ref this.copying, 1) == 1)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
var driveletters = getMicrobitDrives();
|
||||
List<String> drives = new List<String>();
|
||||
foreach (var d in driveletters)
|
||||
{
|
||||
drives.Add(d.RootDirectory.FullName);
|
||||
}
|
||||
if (!String.IsNullOrEmpty(customcopypath) && Directory.Exists(customcopypath))
|
||||
{
|
||||
drives.Add(customcopypath);
|
||||
}
|
||||
if (drives.Count == 0)
|
||||
{
|
||||
this.updateStatus("no board found");
|
||||
this.trayIcon.ShowBalloonTip(3000, "cancelled uploading...", "no board found", ToolTipIcon.None);
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateStatus("uploading .hex file");
|
||||
this.trayIcon.ShowBalloonTip(3000, "uploading...", "uploading .hex file", ToolTipIcon.None);
|
||||
|
||||
// copy to all boards
|
||||
copyFirmware(info.FullName, drives);
|
||||
|
||||
// move away hex file
|
||||
var temp = System.IO.Path.ChangeExtension(info.FullName, ".uploaded.hex");
|
||||
try
|
||||
{
|
||||
File.Copy(info.FullName, temp, true);
|
||||
File.Delete(info.FullName);
|
||||
}
|
||||
catch (IOException) { }
|
||||
catch (NotSupportedException) { }
|
||||
catch (UnauthorizedAccessException) { }
|
||||
catch (ArgumentException) { }
|
||||
|
||||
// update ui
|
||||
this.updateStatus("uploading done");
|
||||
this.waitingForHexFileStatus();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Exchange(ref this.copying, 0);
|
||||
}
|
||||
}
|
||||
catch (IOException) { }
|
||||
catch (NotSupportedException) { }
|
||||
catch (UnauthorizedAccessException) { }
|
||||
catch (ArgumentException) { }
|
||||
}
|
||||
|
||||
static void copyFirmware(string file, List<string> drives)
|
||||
{
|
||||
var waitHandles = new List<WaitHandle>();
|
||||
foreach (var drive in drives)
|
||||
{
|
||||
var ev = new AutoResetEvent(false);
|
||||
waitHandles.Add(ev);
|
||||
ThreadPool.QueueUserWorkItem((state) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var trg = System.IO.Path.Combine(drive, "firmware.hex");
|
||||
File.Copy(file, trg, true);
|
||||
}
|
||||
catch (IOException) { }
|
||||
catch (NotSupportedException) { }
|
||||
catch (UnauthorizedAccessException) { }
|
||||
catch (ArgumentException) { }
|
||||
ev.Set();
|
||||
}, ev);
|
||||
}
|
||||
|
||||
//waits for all the threads (waitHandles) to call the .Set() method
|
||||
//and inform that the execution has finished.
|
||||
WaitHandle.WaitAll(waitHandles.ToArray());
|
||||
}
|
||||
|
||||
static DriveInfo[] getMicrobitDrives()
|
||||
{
|
||||
var drives = System.IO.DriveInfo.GetDrives();
|
||||
var r = new System.Collections.Generic.List<DriveInfo>();
|
||||
foreach (var di in drives)
|
||||
{
|
||||
var label = getVolumeLabel(di);
|
||||
if (label.StartsWith("MICROBIT", StringComparison.Ordinal))
|
||||
r.Add(di);
|
||||
}
|
||||
return r.ToArray();
|
||||
}
|
||||
|
||||
static string getVolumeLabel(DriveInfo di)
|
||||
{
|
||||
try { return di.VolumeLabel; }
|
||||
catch (IOException) { }
|
||||
catch (SecurityException) { }
|
||||
catch (UnauthorizedAccessException) { }
|
||||
return "";
|
||||
}
|
||||
|
||||
private void trayIcon_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.WindowState = FormWindowState.Minimized;
|
||||
this.WindowState = FormWindowState.Normal;
|
||||
this.Show();
|
||||
this.Activate();
|
||||
}
|
||||
|
||||
private void versionLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process.Start("https://codethemicrobit.com/uploader");
|
||||
}
|
||||
catch (IOException) { }
|
||||
}
|
||||
|
||||
private void backgroundPictureBox_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.openEditor();
|
||||
}
|
||||
|
||||
private void SettingsLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
var settings = new Settings(customcopypath);
|
||||
settings.ShowDialog();
|
||||
customcopypath = settings.CustomCopyPath;
|
||||
Application.UserAppDataRegistry.SetValue("CustomDirectory", customcopypath, RegistryValueKind.String);
|
||||
}
|
||||
|
||||
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
this.openEditor();
|
||||
}
|
||||
|
||||
private void pictureBox1_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.openEditor();
|
||||
}
|
||||
}
|
||||
}
|
172
clients/winuploader/Microbit.Uploader/MainForm.resx
Normal file
@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="trayIcon.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="trayIcon.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAMIOAADCDgAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAN6bIZTOkxoUtj62FL5W1hTWpzYUvlbWFLY+thTKgwoUxnb+FLY6shS6TsoUzpMaFL5a1hS2P
|
||||
rYUxnb6FNZ2+ZTCTsvkriaf/KYKe/yuIpf8uk7L/K4il/ymBnP8tjqz/K4qn/yiBnP8qhaL/KoWh/yqG
|
||||
o/8ogJv/JXeQ/yqDnvkRMjz/Di02/wofJv8MJS3/Di02/wskLP8HGB3/Di43/w0qM/8HFxz/CyMr/w4s
|
||||
Nv8MJi7/CiAm/w4sNv8RMTv/BQsN/wUQE/8BAgL/AQQF/wYRFP8EBgf/AgIA/xAYJv8TGy3/AgIA/wMF
|
||||
Bv8HEhX/AQUG/wECAv8FEBT/BQsN/wYFD/8LByT/AQAC/wAAAP8CAgL/AwMD/woKEv8LCxT/DAwY/woK
|
||||
Ev8DAwT/AgIC/wAAAP8AAAD/AAAA/wICAv8JCA//IBs//wwMEP8AAAD/AgIC/wQEBv8bGzf/BgYK/wQE
|
||||
Bf8bGzj/BgYJ/wMDA/8AAAD/CgoK/xEREf8HBwf/Li4u/1FRUf9ERET/AQEA/wwMGf8UFCj/BAQE/wMD
|
||||
Av8DAwL/BAQE/xAQIP8RESL/AAAA/z8/P/9SUlH/NTU1/y4uLv9QUFD/QUFB/wEBAP8LCxf/EhIk/wIC
|
||||
Af8JCRH/CwsV/wICAf8PDx3/Dw8f/wAAAP89PT3/UVFQ/zQ0M/8FBQX/DAwM/wgICP8AAAD/CwsW/xIS
|
||||
JP8FBQb/Dg4b/xERIv8FBQb/Dw8d/w8PHv8AAAD/CAgK/xwXO/8KCRT/BAMI/wAAAP8AAAD/AAAA/wIC
|
||||
Av8EBAX/HR06/wgIEP8GBgv/HR07/wYGCf8DAwL/AAAA/wAAAP8JBh3/BwUS/y0fhf8FBBD/AAAA/wAA
|
||||
AP8AAAD/AAAA/xIOMv8fFVz/HhVa/xQPOP8AAQD/AAAA/wAAAP8AAAD/AAAA/wICAv9UO/v/MiKX/wUD
|
||||
D/8FAw7/AwIK/wAAAP8RCzP/IBZi/yAWYP8TDTr/AAAA/wAAAP8AAAD/AAAA/wAAAP8CAgL/VTz/+FQ6
|
||||
/P8yI5j/IBZg/ywehf8MCCX/BAMN/wUEEP8GBBH/AQED/wAAAP8AAAD/AAAA/wAAAP8AAAD/AgIC9Vc+
|
||||
/2BVOv9+Ujj0fTwptH5ONul9OCapfRUOPn4AAAB+AAAAfQAAAH4AAAB+AAAAfQAAAH4AAAB+AAAAfgQE
|
||||
BFkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA//8AAA==
|
||||
</value>
|
||||
</data>
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAMIOAADCDgAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAN6bIZTOkxoUtj62FL5W1hTWpzYUvlbWFLY+thTKgwoUxnb+FLY6shS6TsoUzpMaFL5a1hS2P
|
||||
rYUxnb6FNZ2+ZTCTsvkriaf/KYKe/yuIpf8uk7L/K4il/ymBnP8tjqz/K4qn/yiBnP8qhaL/KoWh/yqG
|
||||
o/8ogJv/JXeQ/yqDnvkRMjz/Di02/wofJv8MJS3/Di02/wskLP8HGB3/Di43/w0qM/8HFxz/CyMr/w4s
|
||||
Nv8MJi7/CiAm/w4sNv8RMTv/BQsN/wUQE/8BAgL/AQQF/wYRFP8EBgf/AgIA/xAYJv8TGy3/AgIA/wMF
|
||||
Bv8HEhX/AQUG/wECAv8FEBT/BQsN/wYFD/8LByT/AQAC/wAAAP8CAgL/AwMD/woKEv8LCxT/DAwY/woK
|
||||
Ev8DAwT/AgIC/wAAAP8AAAD/AAAA/wICAv8JCA//IBs//wwMEP8AAAD/AgIC/wQEBv8bGzf/BgYK/wQE
|
||||
Bf8bGzj/BgYJ/wMDA/8AAAD/CgoK/xEREf8HBwf/Li4u/1FRUf9ERET/AQEA/wwMGf8UFCj/BAQE/wMD
|
||||
Av8DAwL/BAQE/xAQIP8RESL/AAAA/z8/P/9SUlH/NTU1/y4uLv9QUFD/QUFB/wEBAP8LCxf/EhIk/wIC
|
||||
Af8JCRH/CwsV/wICAf8PDx3/Dw8f/wAAAP89PT3/UVFQ/zQ0M/8FBQX/DAwM/wgICP8AAAD/CwsW/xIS
|
||||
JP8FBQb/Dg4b/xERIv8FBQb/Dw8d/w8PHv8AAAD/CAgK/xwXO/8KCRT/BAMI/wAAAP8AAAD/AAAA/wIC
|
||||
Av8EBAX/HR06/wgIEP8GBgv/HR07/wYGCf8DAwL/AAAA/wAAAP8JBh3/BwUS/y0fhf8FBBD/AAAA/wAA
|
||||
AP8AAAD/AAAA/xIOMv8fFVz/HhVa/xQPOP8AAQD/AAAA/wAAAP8AAAD/AAAA/wICAv9UO/v/MiKX/wUD
|
||||
D/8FAw7/AwIK/wAAAP8RCzP/IBZi/yAWYP8TDTr/AAAA/wAAAP8AAAD/AAAA/wAAAP8CAgL/VTz/+FQ6
|
||||
/P8yI5j/IBZg/ywehf8MCCX/BAMN/wUEEP8GBBH/AQED/wAAAP8AAAD/AAAA/wAAAP8AAAD/AgIC9Vc+
|
||||
/2BVOv9+Ujj0fTwptH5ONul9OCapfRUOPn4AAAB+AAAAfQAAAH4AAAB+AAAAfQAAAH4AAAB+AAAAfgQE
|
||||
BFkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAA//8AAA==
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
30
clients/winuploader/Microbit.Uploader/Program.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Microsoft.VisualBasic.ApplicationServices;
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
SingleInstanceAppStarter.Start(new MainForm(), StartNewInstance);
|
||||
}
|
||||
|
||||
// The handler when attempting to start another instance of this application
|
||||
// We can customize the logic here for which form to activate in different
|
||||
// conditions. Like in this sample, we will be selectively activate the LoginForm
|
||||
// or MainForm based on the login state of the user.
|
||||
static void StartNewInstance(object sender, StartupNextInstanceEventArgs e)
|
||||
{
|
||||
e.BringToForeground = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Code The micro:bit Uploader")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Microsoft")]
|
||||
[assembly: AssemblyProduct("MicrosoftMicrobitUploader")]
|
||||
[assembly: AssemblyCopyright("Copyright © Microsoft 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("7dc6ca45-fd75-44bc-805e-708c812cd4bf")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("0.9.0.0")]
|
||||
[assembly: AssemblyFileVersion("0.9.0.0")]
|
||||
[assembly: CLSCompliant(true)]
|
||||
[assembly: NeutralResourcesLanguage("en-US")]
|
93
clients/winuploader/Microbit.Uploader/Properties/Resources.Designer.cs
generated
Normal file
@ -0,0 +1,93 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.MicroBit.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.MicroBit.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap microbit_red {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("microbit_red", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap MSFT_logo_png {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("MSFT_logo_png", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;}
|
||||
///{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f3\fbidi \froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f10\fbidi \fnil\fcharset2\fp [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string MSR_LA___2576 {
|
||||
get {
|
||||
return ResourceManager.GetString("MSR_LA___2576", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
130
clients/winuploader/Microbit.Uploader/Properties/Resources.resx
Normal file
@ -0,0 +1,130 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="MSR_LA___2576" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\MSR-LA - 2576.rtf;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="MSFT_logo_png" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\MSFT_logo_png.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="microbit_red" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\microbit.red.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
@ -0,0 +1 @@
|
||||
TBD
|
76
clients/winuploader/Microbit.Uploader/Settings.Designer.cs
generated
Normal file
@ -0,0 +1,76 @@
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
partial class Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
this.textBox1.Location = new System.Drawing.Point(107, 12);
|
||||
this.textBox1.Name = "textBox1";
|
||||
this.textBox1.Size = new System.Drawing.Size(100, 20);
|
||||
this.textBox1.TabIndex = 0;
|
||||
this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(34, 15);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(67, 13);
|
||||
this.label1.TabIndex = 1;
|
||||
this.label1.Text = "Custom Path";
|
||||
//
|
||||
// Settings
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(246, 48);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.textBox1);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "Settings";
|
||||
this.ShowIcon = false;
|
||||
this.Text = "Settings";
|
||||
this.Load += new System.EventHandler(this.Settings_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TextBox textBox1;
|
||||
private System.Windows.Forms.Label label1;
|
||||
}
|
||||
}
|
37
clients/winuploader/Microbit.Uploader/Settings.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Security.AccessControl;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
public partial class Settings : Form
|
||||
{
|
||||
public string CustomCopyPath;
|
||||
public Settings(string currentpath)
|
||||
{
|
||||
InitializeComponent();
|
||||
CustomCopyPath = currentpath;
|
||||
|
||||
}
|
||||
|
||||
private void Settings_Load(object sender, EventArgs e)
|
||||
{
|
||||
textBox1.Text = CustomCopyPath;
|
||||
}
|
||||
|
||||
private void label1_Click(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void textBox1_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
CustomCopyPath = textBox1.Text;
|
||||
}
|
||||
}
|
||||
}
|
120
clients/winuploader/Microbit.Uploader/Settings.resx
Normal file
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
@ -0,0 +1,39 @@
|
||||
/****************************** Module Header ******************************\
|
||||
* Module Name: SingleInstanceAppHelper.cs
|
||||
* Project: CSWinFormSingleInstanceApp
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* The sample demonstrates how to achieve the goal that only
|
||||
* one instance of the application is allowed in Windows Forms application..
|
||||
*
|
||||
* This source is subject to the Microsoft Public License.
|
||||
* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
|
||||
* All other rights reserved.
|
||||
*
|
||||
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
\***************************************************************************/
|
||||
|
||||
using System;
|
||||
using Microsoft.VisualBasic.ApplicationServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
// We need to add Microsoft.VisualBasic reference to use
|
||||
// WindowsFormsApplicationBase type.
|
||||
class SingleInstanceApp : WindowsFormsApplicationBase
|
||||
{
|
||||
public SingleInstanceApp()
|
||||
{
|
||||
}
|
||||
public SingleInstanceApp(Form f)
|
||||
{
|
||||
// Set IsSingleInstance property to true to make the application
|
||||
base.IsSingleInstance = true;
|
||||
// Set MainForm of the application.
|
||||
this.MainForm = f;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/****************************** Module Header ******************************\
|
||||
* Module Name: SingleInstanceAppStarter.cs
|
||||
* Project: CSWinFormSingleInstanceApp
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* The sample demonstrates how to achieve the goal that only
|
||||
* one instance of the application is allowed in Windows Forms application..
|
||||
*
|
||||
* This source is subject to the Microsoft Public License.
|
||||
* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
|
||||
* All other rights reserved.
|
||||
*
|
||||
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
||||
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
\***************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.VisualBasic.ApplicationServices;
|
||||
|
||||
namespace Microsoft.MicroBit
|
||||
{
|
||||
internal static class SingleInstanceAppStarter
|
||||
{
|
||||
static SingleInstanceApp app = null;
|
||||
|
||||
// Construct SingleInstanceApp object, and invoke its run method.
|
||||
public static void Start(Form f, StartupNextInstanceEventHandler handler)
|
||||
{
|
||||
if (app == null && f != null)
|
||||
app = new SingleInstanceApp(f);
|
||||
|
||||
// Wire up StartupNextInstance event handler.
|
||||
app.StartupNextInstance += handler;
|
||||
app.Run(Environment.GetCommandLineArgs());
|
||||
}
|
||||
}
|
||||
}
|
BIN
clients/winuploader/Microbit.Uploader/favicon.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
clients/winuploader/Microbit.Uploader/microbit.red.png
Normal file
After Width: | Height: | Size: 21 KiB |
10
cmds/cmds.ts
@ -6,6 +6,8 @@ import * as child_process from "child_process";
|
||||
|
||||
let writeFileAsync: any = Promise.promisify(fs.writeFile)
|
||||
let execAsync: (cmd: string, options?: { cwd?: string }) => Promise<Buffer> = Promise.promisify(child_process.exec)
|
||||
let readDirAsync = Promise.promisify(fs.readdir)
|
||||
|
||||
|
||||
export function deployCoreAsync(res: ts.pxt.CompileResult) {
|
||||
return getBitDrivesAsync()
|
||||
@ -26,17 +28,23 @@ export function deployCoreAsync(res: ts.pxt.CompileResult) {
|
||||
|
||||
function getBitDrivesAsync(): Promise<string[]> {
|
||||
if (process.platform == "win32") {
|
||||
let rx = new RegExp("^([A-Z]:).* " + pxt.appTarget.compile.deployDrives)
|
||||
return execAsync("wmic PATH Win32_LogicalDisk get DeviceID, VolumeName, FileSystem")
|
||||
.then(buf => {
|
||||
let res: string[] = []
|
||||
buf.toString("utf8").split(/\n/).forEach(ln => {
|
||||
let m = /^([A-Z]:).* MICROBIT/.exec(ln)
|
||||
let m = rx.exec(ln)
|
||||
if (m) {
|
||||
res.push(m[1] + "/")
|
||||
}
|
||||
})
|
||||
return res
|
||||
})
|
||||
}
|
||||
else if (process.platform == "darwin") {
|
||||
let rx = new RegExp(pxt.appTarget.compile.deployDrives)
|
||||
return readDirAsync("/Volumes")
|
||||
.then(lst => lst.filter(s => rx.test(s)).map(s => "/Volumes/" + s + "/"))
|
||||
} else {
|
||||
return Promise.resolve([])
|
||||
}
|
||||
|
@ -31,33 +31,33 @@ Just like Arduino, the micro:bit can be connected to and interact with sensors,
|
||||
|
||||
## Hardware: The Device
|
||||
|
||||
Learn about about the [hardware components](/device) of the micro:bit to make the most of it!
|
||||
Learn about the [hardware components](/device) of the micro:bit to make the most of it!
|
||||
|
||||
## Programming: Blocks or JavaScript
|
||||
|
||||
The student can program the BBC micro:bit using [Blocks](/blocks) or [JavaScript](/typescript), via the [micro:bit APIs](/reference):
|
||||
You can program the micro:bit using [Blocks](/blocks) or [JavaScript](/javascript), via the [micro:bit APIs](/reference):
|
||||
|
||||
```blocks
|
||||
basic.showString("Hi!");
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
basic.showString("Hi!");
|
||||
})
|
||||
```
|
||||
|
||||
## Compile and Flash: Your Program!
|
||||
|
||||
When a user has her code ready, she can connect her BBC micro:bit to a computer via a USB cable, so it appears as a mounted drive (named MICROBIT).
|
||||
When you have your code ready, you connect your micro:bit to a computer via a USB cable, so it appears as a mounted drive (named MICROBIT).
|
||||
|
||||
Compilation to ARM thumb machine code from [Blocks](/blocks) or [JavaScript](/typescript) happens in the browser.
|
||||
|
||||
The student is prompted to save the ARM binary program to a file, which she then simply drags to the micro:bit mounted drive,
|
||||
which flashes the micro:bit device with the new program.
|
||||
Compilation to ARM thumb machine code from [Blocks](/blocks) or [JavaScript](/javascript) happens in the browser. You save the ARM binary
|
||||
program to a file, which you then copy to the micro:bit drive, which flashes the micro:bit device with the new program.
|
||||
|
||||
## Simulator: Test Your Code
|
||||
|
||||
Before a student compiles her code for the micro:bit, she can run it using the micro:bit simulator, all within the confines of a web browser.
|
||||
You can run your code using the micro:bit simulator, all within the confines of a web browser.
|
||||
The simulator has support for the LED screen, buttons, as well as compass, accelerometer, and digital I/O pins.
|
||||
|
||||
## C++ Runtime
|
||||
|
||||
The [C++ BBC micro:bit runtime](http://lancaster-university.github.io/microbit-docs/), created at [Lancaster University](http://www.lancaster.ac.uk/), provides access to the hardware functions of the micro:bit,
|
||||
The [C++ micro:bit runtime](http://lancaster-university.github.io/microbit-docs/), created at [Lancaster University](http://www.lancaster.ac.uk/), provides access to the hardware functions of the micro:bit,
|
||||
as well as a set of helper functions (such as displaying a number/image/string on the LED screen).
|
||||
|
||||
The [micro:bit library](/reference) mirrors the functions of the C++ library.
|
||||
@ -65,4 +65,4 @@ When code is compiled to ARM machine code, the calls to JavaScript micro:bit fun
|
||||
|
||||
## Open Source
|
||||
|
||||
The editor for the BBC micro:bit is [open source](/open-source) on GitHub. Contributors are welcome!
|
||||
The code for the micro:bit is [open source](/open-source) on GitHub. Contributors are welcome!
|
||||
|
@ -86,7 +86,7 @@ if (led.point(1,1) && led.point(2,2)) {
|
||||
When you compare two Numbers, you get a Boolean value, such as the comparison `x < 5` in the code below:
|
||||
|
||||
```blocks
|
||||
let x = math.random(5)
|
||||
let x = Math.random(5)
|
||||
if(x < 5) {
|
||||
basic.showString("low");
|
||||
} else {
|
||||
|
@ -1,4 +1,4 @@
|
||||
## Variables
|
||||
# Variables
|
||||
|
||||
[Assign](/blocks/variables/assign) (set) a variable's value
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Device
|
||||
|
||||
All the bits and pieces that make up your BBC micro:bit
|
||||
All the bits and pieces that make up the BBC micro:bit
|
||||
|
||||

|
||||
|
||||
@ -23,13 +23,13 @@ When you have downloaded and run your code onto your micro:bit, press Button R t
|
||||
|
||||
### USB connection
|
||||
|
||||
When you plug in your micro:bit, it should appear as MICROBIT.
|
||||
When you plug in your micro:bit, it should appear as ``MICROBIT``.
|
||||
If you accidentally hold down the reset button as you’re plugging in your micro:bit,
|
||||
the micro:bit will appear as a MAINTENANCE drive instead of MICROBIT. This is known as maintenance mode.**
|
||||
the micro:bit will appear as a MAINTENANCE drive instead of ``MICROBIT``. This is known as maintenance mode.**
|
||||
|
||||
To continue programming your micro:bit YOU MUST unplug your USB and reconnect it. Check that the drive now shows as MICROBIT.
|
||||
To continue programming your micro:bit YOU MUST unplug your USB and reconnect it. Check that the drive now shows as ``MICROBIT``.
|
||||
|
||||
**Use with caution. If you click on the drive while it shows as MAINTENANCE,
|
||||
**Use with caution. If you click on the drive while it shows as ``MAINTENANCE``,
|
||||
you can see which version of firmware you have running on your micro:bit.
|
||||
Firmware on your micro:bit should be up-to-date already.
|
||||
You can find the version of firmware in the 'version.txt' file on the micro:bit. Further information on the firmware can be found here:
|
||||
@ -55,6 +55,10 @@ The pins can be a form of input or output.
|
||||
There are labels for the input/output pins P0, P1, P2, which you can attach external sensors to such as thermometers or moisture detectors.
|
||||
You can read more about large and small pins [here](/device/pins).
|
||||
|
||||
### Light level
|
||||
|
||||
The screen can also be used a light level sensor (it's a really cool trick).
|
||||
|
||||
### How do I connect the micro:bit to my computer?
|
||||
|
||||
Your micro:bit can be connected to your computer via a micro USB cable.
|
||||
@ -73,7 +77,7 @@ You can attach an external device such as a motor to these and power it using th
|
||||
|
||||
### Serial Communication
|
||||
|
||||
The BBC micro:bit can send an receive data via [serial communication](/device/serial). The serial data can be transfered via USB or BlE.
|
||||
The micro:bit can send an receive data via [serial communication](/device/serial). The serial data can be transfered via USB or BLE.
|
||||
|
||||
### Bluetooth Low Energy (BLE) Antenna
|
||||
|
||||
|
@ -29,13 +29,21 @@ Unfortunately, using the serial library requires quite a bit of a setup.
|
||||
If you are using the Google Chrome browser, you can use our extension to get serial data streaming in the editor.
|
||||
|
||||
* Install the [Extension for BBC micro:bit](https://chrome.google.com/webstore/detail/extension-for-bbc-microbi/cihhkhnngbjlhahcfmhekmbnnjcjdbge?hl=en-US) on the Chrome Web Store.
|
||||
* Restart Chrome and open the web editor.
|
||||
* Restart Chrome and open the [web editor](https://codethemicrobit.com)
|
||||
* The serial data will show below the simulator
|
||||
|
||||
### Windows
|
||||
|
||||
You must install a device driver (for the computer to recognize the serial interface of the micro:bit); then, you must also install a terminal emulator (which is going to connect to the micro:bit and read its output). Here's how to do it:
|
||||
You must install a device driver (for the computer to recognize the
|
||||
serial interface of the micro:bit); then, you must also install a
|
||||
terminal emulator (which is going to connect to the micro:bit and read
|
||||
its output).
|
||||
|
||||
* Follow instructions at https://developer.mbed.org/handbook/Windows-serial-configuration in order to install the device driver
|
||||
* Follow the instructions at
|
||||
https://developer.mbed.org/handbook/Windows-serial-configuration to
|
||||
install the device driver.
|
||||
|
||||
* Instructions for installing a terminal emulator are below.
|
||||
|
||||
#### Windows > Tera Term
|
||||
|
||||
@ -66,14 +74,16 @@ If you prefer another terminal emulator (such as [PuTTY](http://www.putty.org/))
|
||||
|
||||
### Linux
|
||||
|
||||
(Untested).
|
||||
* Install the program `screen` if it is not already installed.
|
||||
* Plug in the micro:bit.
|
||||
* Open a terminal.
|
||||
* Find which device node the micro:bit was assigned to with the command `ls /dev/ttyACM*`.
|
||||
* If it was `/dev/ttyACM0`, type the command `screen /dev/ttyACM0 115200`. If it was some other device node,
|
||||
use that one in the command instead. **Note:** You may need root access to run `screen`
|
||||
successfully. You can probably use the command `sudo` like this: `sudo screen /dev/ttyACM0 115200`.
|
||||
* To exit `screen`, type `Ctrl-A` `Ctrl-D`.
|
||||
|
||||
* Plug in the micro:bit
|
||||
* Open a terminal
|
||||
* `dmesg | tail` will show you which `/dev/` node the micro:bit was assigned (e.g. `/dev/ttyUSB0`)
|
||||
* Then, do: `screen /dev/ttyUSB0 115200` (install the `screen` program if you don't have it). To exit, run `Ctrl-A` `Ctrl-D`.
|
||||
|
||||
Alternative programs include minicom, etc.
|
||||
Alternative programs include `minicom` and so on.
|
||||
|
||||
### Mac OS
|
||||
|
||||
|
50
docs/docs.md
@ -1,36 +1,26 @@
|
||||
# Documentation
|
||||
|
||||
```sim
|
||||
basic.forever(() => {
|
||||
basic.showString("DOCS ");
|
||||
})
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
led.stopAnimation();
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
# . . . #
|
||||
. # # # .`);
|
||||
});
|
||||
input.onButtonPressed(Button.B, () => {
|
||||
led.stopAnimation();
|
||||
basic.showLeds(`
|
||||
. # . # .
|
||||
# . # . #
|
||||
# . . . #
|
||||
. # . # .
|
||||
. . # . .`);
|
||||
});
|
||||
```
|
||||
### Things to do
|
||||
|
||||
* **[getting started](/getting-started)**
|
||||
* Get started with [projects](/projects)
|
||||
* Browse the [micro:bit APIs](/reference)
|
||||
* Learn more about the [micro:bit device](/device)
|
||||
* Frequently Asked Question [faq](/faq)
|
||||
* Follow up with the [release notes](/release-notes)
|
||||
* **[Getting Started](/getting-started)**
|
||||
* [Ten projects](/projects)
|
||||
|
||||
### Micro:bit reference
|
||||
|
||||
* [The micro:bit APIs](/reference)
|
||||
* [The micro:bit device](/device)
|
||||
|
||||
### Language and data reference
|
||||
|
||||
* [Blocks language](/blocks)
|
||||
* [JavaScript language](/javascript)
|
||||
* [Streaming data](/streaming)
|
||||
|
||||
### More questions?
|
||||
|
||||
* [Frequently Asked Question](/faq)
|
||||
* [Release notes](/release-notes)
|
||||
|
||||
### Developers
|
||||
|
||||
* Learn about [packages](/packages) (possibly using C++ or ARM thumb)
|
||||
* Learn about [packages](/packages)
|
||||
|
@ -1,6 +1,12 @@
|
||||
# Frequently Asked Questions
|
||||
|
||||
## Where can I get a BBC micro:bit?
|
||||
### Where can I get a BBC micro:bit?
|
||||
|
||||
More information at [http://uk.farnell.com/bbc-microbit](http://uk.farnell.com/bbc-microbit).
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### My micro:bit does not show up as a drive when I connect it to my computer.
|
||||
|
||||
A common cause for this is a broken cable. Pick another USB cable and try it. Otherwise, try another computer as well.
|
@ -2,17 +2,13 @@
|
||||
|
||||
## ~avatar
|
||||
|
||||
Are you ready to build cool BBC micro:bit programs?
|
||||
|
||||
Here are some challenges for you. Arrange the blocks in the editor
|
||||
to make real programs that work!
|
||||
|
||||
## ~
|
||||
|
||||
### Happy face
|
||||
|
||||
There are three blocks in the editor (the area to the left).
|
||||
Arrange them to look like this:
|
||||
Use the **Basic** drawer in the editor
|
||||
to drag out and arrange three blocks to create this program:
|
||||
|
||||
```blocks
|
||||
basic.forever(() => {
|
||||
@ -33,470 +29,13 @@ basic.forever(() => {
|
||||
});
|
||||
```
|
||||
|
||||
When you run this program, you will see a smiley face, then a blank
|
||||
When this program runs, you will see a smiley face, then a blank
|
||||
screen, then a smiley again -- it never stops! (That's because of the
|
||||
``forever`` block.)
|
||||
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
Make sure to follow the instructions.
|
||||
|
||||
### Happy unhappy face
|
||||
|
||||
Draw an unhappy face instead of the blank screen. Click on the dots
|
||||
in the second ``show leds`` block until it matches the blocks below.
|
||||
Now you have an **animation** (cartoon) that shows a happy face,
|
||||
then an unhappy one, then a happy one again, forever (or until
|
||||
you turn off your micro:bit)!
|
||||
|
||||
```blocks
|
||||
basic.forever(() => {
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
# . . . #
|
||||
. # # # .
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
. # # # .
|
||||
# . . . #
|
||||
`)
|
||||
});
|
||||
```
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
### Your turn!
|
||||
|
||||
Pile up more ``show leds`` blocks to create your animation! Create an
|
||||
animation with at least 5 pictures. What does this animation show?
|
||||
|
||||
```blocks
|
||||
basic.forever(() => {
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
# . . . #
|
||||
. # # # .
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
# # # # #
|
||||
. . . . .
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
. # # # .
|
||||
# . . . #
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
# # # # #
|
||||
. . . # #
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
# . # . .
|
||||
. . . . .
|
||||
# . . . #
|
||||
. # # # .
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. . # . #
|
||||
. . . . .
|
||||
# . . . #
|
||||
. # # # .
|
||||
`)
|
||||
});
|
||||
```
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
#### ~hint
|
||||
|
||||
You can find the ``show leds`` block in the **Basic** part of the editor.
|
||||
|
||||
#### ~
|
||||
|
||||
### Button A and button B
|
||||
|
||||
This program will show the word **ANTEATER** on the LED
|
||||
screen when you press button `A`.
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
basic.showString("ANTEATER");
|
||||
});
|
||||
```
|
||||
|
||||
#### ~hint
|
||||
|
||||
The ``showString`` block can show letters, numbers, and punctuation
|
||||
on the micro:bit screen.
|
||||
|
||||
#### ~
|
||||
|
||||
Now try to unscramble these blocks in the editor so that the micro:bit
|
||||
shows **BANANA** when you press button `B`.
|
||||
|
||||
```shuffle
|
||||
input.onButtonPressed(Button.B, () => {
|
||||
basic.showString("BANANA");
|
||||
});
|
||||
```
|
||||
#### ~hint
|
||||
|
||||
You can find the letter `B` by clicking the letter `A` on the
|
||||
``onButtonPressed`` block.
|
||||
|
||||
#### ~
|
||||
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
#### Your turn!
|
||||
|
||||
Can you combine these blocks so your program shows your real name
|
||||
instead of **ANTEATER** when you press `A`, but _your secret agent
|
||||
name_ instead of **BANANA** when you press `B`?
|
||||
|
||||
### Shake
|
||||
|
||||
You can find when someone is shaking the BBC micro:bit by checking its
|
||||
**accelerometer** (it finds whether the micro:bit is speeding up or
|
||||
slowing down).
|
||||
|
||||
Unscramble these blocks in the editor to show a frownie when someone
|
||||
shakes the micro:bit. (Ouch!)
|
||||
|
||||
```shuffle
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
. # # # .
|
||||
# . . . #`);
|
||||
});
|
||||
```
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
### Pins
|
||||
|
||||
You can also use the pins as buttons. (The pins are the holes in the
|
||||
metal stripe at the bottom of the micro:bit board.) For example, hold
|
||||
the ``GND`` button with one hand and touch the ``0`` pin (called
|
||||
``P0``) with your other hand to tell the micro:bit you're pressing it.
|
||||
|
||||
Unscramble the blocks in the editor to show a heart when you touch
|
||||
pin ``P0``.
|
||||
|
||||
```shuffle
|
||||
input.onPinPressed(TouchPin.P0, () => {
|
||||
basic.showLeds(`
|
||||
. # . # .
|
||||
# . # . #
|
||||
# . . . #
|
||||
. # . # .
|
||||
. . # . .`);
|
||||
});
|
||||
```
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
## ~hint
|
||||
|
||||
Try this experiment: find a friend and hold hands. Touch the ``GND``
|
||||
pin while your friend presses the ``P0`` pin. You should see the
|
||||
heart! The electric current is going through your bodies and across
|
||||
your handshake to make it happen!
|
||||
|
||||
## ~
|
||||
|
||||
## The amazing coin flipper
|
||||
|
||||
### ~avatar avatar
|
||||
|
||||
Are you trying to choose whether to play soccer or go to the movies
|
||||
instead, or which toppings to have on your pizza? Build a coin
|
||||
flipping machine with the BBC micro:bit to choose for you!
|
||||
|
||||
### ~
|
||||
|
||||
Here are the blocks to make your coin flipper. When you press button
|
||||
`B`, the coin flipper will show either `H` for heads or `T` for tails
|
||||
on the LED screen.
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.B, () => {
|
||||
if (Math.randomBoolean()) {
|
||||
basic.showString("H");
|
||||
} else {
|
||||
basic.showString("T");
|
||||
}
|
||||
});
|
||||
```
|
||||
### ~hint
|
||||
|
||||
The ``pick random true or false`` block randomly tells the ``if``
|
||||
block `true` or `false`. If the ``pick`` block picked `true`, the
|
||||
``if`` block shows the letter `H`. Otherwise, it shows the letter `T`.
|
||||
|
||||
That's it!
|
||||
|
||||
### ~
|
||||
|
||||
### Keeping score
|
||||
|
||||
#### ~avatar
|
||||
|
||||
To keep track out of how many guesses you've won,
|
||||
add these blocks to your coin flipper:
|
||||
|
||||
#### ~
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
game.addScore(1);
|
||||
});
|
||||
input.onButtonPressed(Button.AB, () => {
|
||||
basic.showNumber(game.score());
|
||||
});
|
||||
```
|
||||
|
||||
These blocks mean that if you press button `A`, you will add `1` to
|
||||
your score, and if you press `A` and `B` together, the micro:bit will
|
||||
show your score.
|
||||
|
||||
When you're done, your coin flipping program should look like this:
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.B, () => {
|
||||
if (Math.randomBoolean()) {
|
||||
basic.showString("H");
|
||||
} else {
|
||||
basic.showString("T");
|
||||
}
|
||||
});
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
game.addScore(1);
|
||||
});
|
||||
input.onButtonPressed(Button.AB, () => {
|
||||
basic.showNumber(game.score());
|
||||
});
|
||||
```
|
||||
|
||||
Flip until your thumbs get tired!
|
||||
|
||||
## Let's play Rock Paper Scissors!
|
||||
|
||||
### ~avatar avatar
|
||||
|
||||
Build a Rock Paper Scissors game with the BBC micro:bit! You can play
|
||||
the game with a friend who has it on a micro:bit. You can also play
|
||||
it with friends who are just using their hands. (The game is built
|
||||
like a coin flipper, but with three choices instead of two.)
|
||||
|
||||
### ~
|
||||
|
||||
## Step 1: Getting started
|
||||
|
||||
We want the micro:bit to choose rock, paper, or scissors when you
|
||||
shake it. Try creating an ``on shake`` block so when you shake the
|
||||
micro:bit, it will run part of a program.
|
||||
|
||||
Clear up the blocks and add the blocks below.
|
||||
|
||||
```blocks
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
Next, when you shake the micro:bit, it should pick a random number from `0` to `2`
|
||||
and store it in the variable `item`.
|
||||
|
||||
Add a ``set`` block with a variable. Then add a ``pick random`` block,
|
||||
and store the random number in the variable,
|
||||
like this:
|
||||
|
||||
```blocks
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
let item = Math.random(3)
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
### ~hint
|
||||
No one can predict random numbers. That's what makes them great for Rock Paper Scissors!
|
||||
### ~
|
||||
|
||||
Each possible number these blocks can make (`0`, `1`, or `2`) means a different picture.
|
||||
We will show the right picture for that number on the LED screen.
|
||||
|
||||
|
||||
## Step 2: Picking paper
|
||||
|
||||
Put an ``if`` block after the ``let`` block that checks whether
|
||||
`item` is `0`. Make sure the ``if`` block has an ``else if`` part
|
||||
and an ``else`` part.
|
||||
|
||||
Next, add a ``show leds`` block that shows a
|
||||
picture of a piece of paper:
|
||||
|
||||
```blocks
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
let item = Math.random(3)
|
||||
if (item == 0) {
|
||||
basic.showLeds(`
|
||||
# # # # #
|
||||
# . . . #
|
||||
# . . . #
|
||||
# . . . #
|
||||
# # # # #
|
||||
`)
|
||||
} else if (false) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Step 3: A random rock
|
||||
|
||||
Now we are going to add a new picture for the micro:bit to show
|
||||
when another random number comes up.
|
||||
|
||||
Make the ``else if`` part check if the variable `item` is `1`.
|
||||
Then add a ``show leds`` block with a picture of a rock.
|
||||
|
||||
```blocks
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
let item = Math.random(3)
|
||||
if (item == 0) {
|
||||
basic.showLeds(`
|
||||
# # # # #
|
||||
# . . . #
|
||||
# . . . #
|
||||
# . . . #
|
||||
# # # # #
|
||||
`)
|
||||
} else if (item == 1) {
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # # # .
|
||||
. # # # .
|
||||
. # # # .
|
||||
. . . . .
|
||||
`)
|
||||
} else {
|
||||
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Step 4: Suddenly scissors
|
||||
|
||||
Add a ``show leds`` block with a picture of scissors to the ``else`` part:
|
||||
|
||||
```blocks
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
let item = Math.random(3)
|
||||
if (item == 0) {
|
||||
basic.showLeds(`
|
||||
# # # # #
|
||||
# . . . #
|
||||
# . . . #
|
||||
# . . . #
|
||||
# # # # #
|
||||
`)
|
||||
|
||||
} else if (item == 1) {
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # # # .
|
||||
. # # # .
|
||||
. # # # .
|
||||
. . . . .
|
||||
`)
|
||||
} else {
|
||||
basic.showLeds(`
|
||||
# # . . #
|
||||
# # . # .
|
||||
. . # . .
|
||||
# # . # .
|
||||
# # . . #
|
||||
`)
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
### ~hint
|
||||
|
||||
You don't need to check if `item` is `2` because `2` is the only number left out of `0`, `1`, and `2`.
|
||||
That's why you can use an ``else`` instead of an ``else if``.
|
||||
|
||||
### ~
|
||||
|
||||
Your game is ready!
|
||||
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
Have fun!
|
||||
|
||||
## Step 5: Are you the greatest?
|
||||
|
||||
Here is a way you can make your Rock Paper Scissors game better.
|
||||
When button ``A`` is pressed,
|
||||
the micro:bit will add `1` to your score.
|
||||
|
||||
Open the ``Game`` drawer, and then add the block ``change score by 1`` to your program,
|
||||
like this:
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
game.addScore(1)
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
## Step 6: Prove you're the greatest!
|
||||
|
||||
After your micro:bit can add `1` to the score, show how many wins you have.
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
game.addScore(1)
|
||||
basic.showString("WINS:")
|
||||
basic.showNumber(game.score())
|
||||
})
|
||||
```
|
||||
## Step 7: Staying honest
|
||||
|
||||
Success! Your micro:bit can track wins!
|
||||
But what about losses?
|
||||
Use the ``Game`` drawer to subtract `1` from your score when you press button `B`.
|
||||
|
||||
Here are all the blocks you will need:
|
||||
|
||||
```shuffle
|
||||
input.onButtonPressed(Button.B, () => {
|
||||
game.addScore(-1)
|
||||
basic.showString("LOSSES:")
|
||||
basic.showNumber(game.score())
|
||||
})
|
||||
```
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
## Your turn!
|
||||
|
||||
How else can you make your game better?
|
||||
Ever hear of [Rock Paper Scissors Spock Lizard](http://www.samkass.com/theories/RPSSL.html)?
|
||||
### ~button /getting-started/screen
|
||||
NEXT: THE SCREEN
|
||||
### ~
|
81
docs/getting-started/buttons.md
Normal file
@ -0,0 +1,81 @@
|
||||
# Button A and button B
|
||||
|
||||
### ~avatar avatar
|
||||
|
||||
Buttons are great to build games!
|
||||
|
||||
### ~
|
||||
|
||||
This program will show the word **ANTEATER** on the LED
|
||||
screen when you press button `A`.
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
basic.showString("ANTEATER");
|
||||
});
|
||||
```
|
||||
|
||||
#### ~hint
|
||||
|
||||
The ``showString`` block can show letters, numbers, and punctuation
|
||||
on the micro:bit screen.
|
||||
|
||||
#### ~
|
||||
|
||||
Now try to unscramble these blocks in the editor so that the micro:bit
|
||||
shows **BANANA** when you press button `B`.
|
||||
|
||||
```shuffle
|
||||
input.onButtonPressed(Button.B, () => {
|
||||
basic.showString("BANANA");
|
||||
});
|
||||
```
|
||||
#### ~hint
|
||||
|
||||
You can find the letter `B` by clicking the letter `A` on the
|
||||
``onButtonPressed`` block.
|
||||
|
||||
#### ~
|
||||
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
#### Your turn!
|
||||
|
||||
Can you combine these blocks so your program shows your real name
|
||||
instead of **ANTEATER** when you press `A`, but _your secret agent
|
||||
name_ instead of **BANANA** when you press `B`?
|
||||
|
||||
### Pins
|
||||
|
||||
You can also use the pins as buttons. (The pins are the holes in the
|
||||
metal stripe at the bottom of the micro:bit board.) For example, hold
|
||||
the ``GND`` button with one hand and touch the ``0`` pin (called
|
||||
``P0``) with your other hand to tell the micro:bit you're pressing it.
|
||||
|
||||
Unscramble the blocks in the editor to show a heart when you touch
|
||||
pin ``P0``.
|
||||
|
||||
```shuffle
|
||||
input.onPinPressed(TouchPin.P0, () => {
|
||||
basic.showLeds(`
|
||||
. # . # .
|
||||
# . # . #
|
||||
# . . . #
|
||||
. # . # .
|
||||
. . # . .`);
|
||||
});
|
||||
```
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
## ~hint
|
||||
|
||||
Try this experiment: find a friend and hold hands. Touch the ``GND``
|
||||
pin while your friend presses the ``P0`` pin. You should see the
|
||||
heart! The electric current is going through your bodies and across
|
||||
your handshake to make it happen!
|
||||
|
||||
## ~
|
||||
|
||||
### ~button /getting-started/shake
|
||||
NEXT: SHAKE
|
||||
### ~
|
78
docs/getting-started/coin-flipper.md
Normal file
@ -0,0 +1,78 @@
|
||||
# The amazing coin flipper
|
||||
|
||||
### ~avatar avatar
|
||||
|
||||
Are you trying to choose whether to play soccer or go to the movies
|
||||
instead, or which toppings to have on your pizza? Build a coin
|
||||
flipping machine with the BBC micro:bit to choose for you!
|
||||
|
||||
### ~
|
||||
|
||||
Here are the blocks to make your coin flipper. When you press button
|
||||
`B`, the coin flipper will show either `H` for heads or `T` for tails
|
||||
on the LED screen.
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.B, () => {
|
||||
if (Math.randomBoolean()) {
|
||||
basic.showString("H");
|
||||
} else {
|
||||
basic.showString("T");
|
||||
}
|
||||
});
|
||||
```
|
||||
### ~hint
|
||||
|
||||
The ``pick random true or false`` block randomly tells the ``if``
|
||||
block `true` or `false`. If the ``pick`` block picked `true`, the
|
||||
``if`` block shows the letter `H`. Otherwise, it shows the letter `T`.
|
||||
|
||||
That's it!
|
||||
|
||||
### ~
|
||||
|
||||
### Keeping score
|
||||
|
||||
#### ~avatar
|
||||
|
||||
To keep track out of how many guesses you've won,
|
||||
add these blocks to your coin flipper:
|
||||
|
||||
#### ~
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
game.addScore(1);
|
||||
});
|
||||
input.onButtonPressed(Button.AB, () => {
|
||||
basic.showNumber(game.score());
|
||||
});
|
||||
```
|
||||
|
||||
These blocks mean that if you press button `A`, you will add `1` to
|
||||
your score, and if you press `A` and `B` together, the micro:bit will
|
||||
show your score.
|
||||
|
||||
When you're done, your coin flipping program should look like this:
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.B, () => {
|
||||
if (Math.randomBoolean()) {
|
||||
basic.showString("H");
|
||||
} else {
|
||||
basic.showString("T");
|
||||
}
|
||||
});
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
game.addScore(1);
|
||||
});
|
||||
input.onButtonPressed(Button.AB, () => {
|
||||
basic.showNumber(game.score());
|
||||
});
|
||||
```
|
||||
|
||||
Flip until your thumbs get tired!
|
||||
|
||||
### ~button /getting-started/rock-paper-scissors
|
||||
NEXT: ROCK PAPER SCISSORS
|
||||
### ~
|
205
docs/getting-started/rock-paper-scissors.md
Normal file
@ -0,0 +1,205 @@
|
||||
# Rock Paper Scissors
|
||||
|
||||
### ~avatar avatar
|
||||
|
||||
Build a Rock Paper Scissors game with the BBC micro:bit! You can play
|
||||
the game with a friend who has it on a micro:bit. You can also play
|
||||
it with friends who are just using their hands. (The game is built
|
||||
like a coin flipper, but with three choices instead of two.)
|
||||
|
||||
### ~
|
||||
|
||||
## Step 1: Getting started
|
||||
|
||||
We want the micro:bit to choose rock, paper, or scissors when you
|
||||
shake it. Try creating an ``on shake`` block so when you shake the
|
||||
micro:bit, it will run part of a program.
|
||||
|
||||
Clear up the blocks and add the blocks below.
|
||||
|
||||
```blocks
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
Next, when you shake the micro:bit, it should pick a random number from `0` to `2`
|
||||
and store it in the variable `item`.
|
||||
|
||||
Add a ``set`` block with a variable. Then add a ``pick random`` block,
|
||||
and store the random number in the variable,
|
||||
like this:
|
||||
|
||||
```blocks
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
let item = Math.random(3)
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
### ~hint
|
||||
No one can predict random numbers. That's what makes them great for Rock Paper Scissors!
|
||||
### ~
|
||||
|
||||
Each possible number these blocks can make (`0`, `1`, or `2`) means a different picture.
|
||||
We will show the right picture for that number on the LED screen.
|
||||
|
||||
|
||||
## Step 2: Picking paper
|
||||
|
||||
Put an ``if`` block after the ``let`` block that checks whether
|
||||
`item` is `0`. Make sure the ``if`` block has an ``else if`` part
|
||||
and an ``else`` part.
|
||||
|
||||
Next, add a ``show leds`` block that shows a
|
||||
picture of a piece of paper:
|
||||
|
||||
```blocks
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
let item = Math.random(3)
|
||||
if (item == 0) {
|
||||
basic.showLeds(`
|
||||
# # # # #
|
||||
# . . . #
|
||||
# . . . #
|
||||
# . . . #
|
||||
# # # # #
|
||||
`)
|
||||
} else if (false) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Step 3: A random rock
|
||||
|
||||
Now we are going to add a new picture for the micro:bit to show
|
||||
when another random number comes up.
|
||||
|
||||
Make the ``else if`` part check if the variable `item` is `1`.
|
||||
Then add a ``show leds`` block with a picture of a rock.
|
||||
|
||||
```blocks
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
let item = Math.random(3)
|
||||
if (item == 0) {
|
||||
basic.showLeds(`
|
||||
# # # # #
|
||||
# . . . #
|
||||
# . . . #
|
||||
# . . . #
|
||||
# # # # #
|
||||
`)
|
||||
} else if (item == 1) {
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # # # .
|
||||
. # # # .
|
||||
. # # # .
|
||||
. . . . .
|
||||
`)
|
||||
} else {
|
||||
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Step 4: Suddenly scissors
|
||||
|
||||
Add a ``show leds`` block with a picture of scissors to the ``else`` part:
|
||||
|
||||
```blocks
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
let item = Math.random(3)
|
||||
if (item == 0) {
|
||||
basic.showLeds(`
|
||||
# # # # #
|
||||
# . . . #
|
||||
# . . . #
|
||||
# . . . #
|
||||
# # # # #
|
||||
`)
|
||||
|
||||
} else if (item == 1) {
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # # # .
|
||||
. # # # .
|
||||
. # # # .
|
||||
. . . . .
|
||||
`)
|
||||
} else {
|
||||
basic.showLeds(`
|
||||
# # . . #
|
||||
# # . # .
|
||||
. . # . .
|
||||
# # . # .
|
||||
# # . . #
|
||||
`)
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
### ~hint
|
||||
|
||||
You don't need to check if `item` is `2` because `2` is the only number left out of `0`, `1`, and `2`.
|
||||
That's why you can use an ``else`` instead of an ``else if``.
|
||||
|
||||
### ~
|
||||
|
||||
Your game is ready!
|
||||
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
Have fun!
|
||||
|
||||
## Step 5: Are you the greatest?
|
||||
|
||||
Here is a way you can make your Rock Paper Scissors game better.
|
||||
When button ``A`` is pressed,
|
||||
the micro:bit will add `1` to your score.
|
||||
|
||||
Open the ``Game`` drawer, and then add the block ``change score by 1`` to your program,
|
||||
like this:
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
game.addScore(1)
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
## Step 6: Prove you're the greatest!
|
||||
|
||||
After your micro:bit can add `1` to the score, show how many wins you have.
|
||||
|
||||
```blocks
|
||||
input.onButtonPressed(Button.A, () => {
|
||||
game.addScore(1)
|
||||
basic.showString("WINS:")
|
||||
basic.showNumber(game.score())
|
||||
})
|
||||
```
|
||||
## Step 7: Staying honest
|
||||
|
||||
Success! Your micro:bit can track wins!
|
||||
But what about losses?
|
||||
Use the ``Game`` drawer to subtract `1` from your score when you press button `B`.
|
||||
|
||||
Here are all the blocks you will need:
|
||||
|
||||
```shuffle
|
||||
input.onButtonPressed(Button.B, () => {
|
||||
game.addScore(-1)
|
||||
basic.showString("LOSSES:")
|
||||
basic.showNumber(game.score())
|
||||
})
|
||||
```
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
### ~button /projects
|
||||
NEXT: PROJECTS!
|
||||
### ~
|
98
docs/getting-started/screen.md
Normal file
@ -0,0 +1,98 @@
|
||||
# Screen
|
||||
|
||||
### ~avatar avatar
|
||||
|
||||
There are 25 bright LEDs on the micro:bit screen. Let's use them to create some cool animations!
|
||||
|
||||
### ~
|
||||
|
||||
### Happy unhappy face
|
||||
|
||||
Draw an unhappy face instead of the blank screen. Click on the dots
|
||||
in the second ``show leds`` block until it matches the blocks below.
|
||||
Now you have an **animation** (cartoon) that shows a happy face,
|
||||
then an unhappy one, then a happy one again, forever (or until
|
||||
you turn off your micro:bit)!
|
||||
|
||||
```blocks
|
||||
basic.forever(() => {
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
# . . . #
|
||||
. # # # .
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
. # # # .
|
||||
# . . . #
|
||||
`)
|
||||
});
|
||||
```
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
### Your turn!
|
||||
|
||||
Pile up more ``show leds`` blocks to create an animation! Create an
|
||||
animation with at least 5 pictures. What does this animation show?
|
||||
|
||||
```blocks
|
||||
basic.forever(() => {
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
# . . . #
|
||||
. # # # .
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
# # # # #
|
||||
. . . . .
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
. # # # .
|
||||
# . . . #
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
# # # # #
|
||||
. . . # #
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
# . # . .
|
||||
. . . . .
|
||||
# . . . #
|
||||
. # # # .
|
||||
`)
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. . # . #
|
||||
. . . . .
|
||||
# . . . #
|
||||
. # # # .
|
||||
`)
|
||||
});
|
||||
```
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
#### ~hint
|
||||
|
||||
You can find the ``show leds`` block in the **Basic** part of the editor.
|
||||
|
||||
#### ~
|
||||
|
||||
### ~button /getting-started/buttons
|
||||
NEXT: BUTTONS
|
||||
### ~
|
24
docs/getting-started/shake.md
Normal file
@ -0,0 +1,24 @@
|
||||
# Shake
|
||||
|
||||
You can find when someone is shaking the BBC micro:bit by checking its
|
||||
**accelerometer** (it finds whether the micro:bit is speeding up or
|
||||
slowing down).
|
||||
|
||||
Unscramble these blocks in the editor to show a frownie when someone
|
||||
shakes the micro:bit. (Ouch!)
|
||||
|
||||
```shuffle
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
basic.showLeds(`
|
||||
. . . . .
|
||||
. # . # .
|
||||
. . . . .
|
||||
. # # # .
|
||||
# . . . #`);
|
||||
});
|
||||
```
|
||||
Click **Compile** to move your program to the BBC micro:bit!
|
||||
|
||||
### ~button /getting-started/coin-flipper
|
||||
NEXT: COIN FLIPPER GAME
|
||||
### ~
|
36
docs/javascript.md
Normal file
@ -0,0 +1,36 @@
|
||||
# JavaScript and TypeScript
|
||||
|
||||
Visit the cards below to starting programming JavaScript and TypeScript with the micro:bit:
|
||||
|
||||
```codecard
|
||||
[{
|
||||
"name": "Calling",
|
||||
"url": "/js/call"
|
||||
},{
|
||||
"name": "Sequencing",
|
||||
"url": "/js/sequence"
|
||||
},{
|
||||
"name": "Variables",
|
||||
"url": "/js/variables"
|
||||
},{
|
||||
"name": "Operators",
|
||||
"url": "/js/operators"
|
||||
},{
|
||||
"name": "Statements",
|
||||
"url": "/js/statements"
|
||||
},{
|
||||
"name": "Functions",
|
||||
"url": "/js/functions"
|
||||
},{
|
||||
"name": "Types",
|
||||
"url": "/js/types"
|
||||
},{
|
||||
"name": "Classes",
|
||||
"url": "/js/classes"
|
||||
},{
|
||||
"name": "FAQ",
|
||||
"url": "/js/faq"
|
||||
}
|
||||
]
|
||||
|
||||
```
|
58
docs/js/call.md
Normal file
@ -0,0 +1,58 @@
|
||||
# Call a function
|
||||
|
||||
The simplest way to get started in JavaScript with your micro:bit is to
|
||||
call one of the micro:bit's built-in JavaScript functions. Just like Blocks
|
||||
are organized into categories/drawers, the micro:bit functions are organized by
|
||||
namespaces, with names corresponding to the drawer names. The `basic` namespace
|
||||
contains a number of helpful functions, such as:
|
||||
|
||||
```typescript
|
||||
basic.showString("Hello!")
|
||||
```
|
||||
|
||||
If you want to see all functions available in the `basic` namespace, simply type `basic`
|
||||
followed by `.` and a list of all the functions will appear.
|
||||
|
||||

|
||||
|
||||
This feature is known as "Intellisense". Continue typing to select one of the functions,
|
||||
or click on one of the functions to select. You also narrow down the set of functions by typing, as below:
|
||||
|
||||

|
||||
|
||||
You can type anything to see what Intellisense will find for you. Here's an example
|
||||
of what happens when you type the word `for`:
|
||||

|
||||
|
||||
## Function parameter values
|
||||
|
||||
You might have noticed that the call `showString` above takes one parameter value,
|
||||
the string to be scrolled on the LED screen. There is a second (optional)
|
||||
parameter that controls the speed of the scroll. Try this:
|
||||
|
||||
```typescript
|
||||
basic.showString("Hello!",50)
|
||||
```
|
||||
|
||||
Intellisense shows all the available parameters for a function.
|
||||
|
||||
## Left and right parentheses, please!
|
||||
|
||||
Whenever you want to call a function, you give the name of the function
|
||||
followed by `(` and ending with `)`. Inbetween the left and right
|
||||
parentheses go the function arguments. If a function has zero arguments, you still
|
||||
need the parentheses in order to call the function. For example
|
||||
|
||||
```typescript
|
||||
basic.clearScreen()
|
||||
```
|
||||
|
||||
It's a syntax error to have a left parenthesis without the "closing" right parenthesis:
|
||||
|
||||
```typescript
|
||||
basic.clearScreen(
|
||||
```
|
||||
|
||||
### ~button /js/sequence
|
||||
NEXT: Sequencing Commands
|
||||
### ~
|
268
docs/js/classes.md
Normal file
@ -0,0 +1,268 @@
|
||||
# Classes
|
||||
|
||||
Traditional JavaScript focuses on functions and prototype-based inheritance as the basic means of building up reusable components,
|
||||
but this may feel a bit awkward to programmers more comfortable with an object-oriented approach, where classes inherit functionality
|
||||
and objects are built from these classes.
|
||||
|
||||
Starting with ECMAScript 2015, also known as ECMAScript 6, JavaScript programmers will be able to build their applications using
|
||||
this object-oriented class-based approach. TypeScript, allows you to use these techniques now, compiling them
|
||||
down to JavaScript that works across all major browsers and platforms, without having to wait for the next version of JavaScript.
|
||||
|
||||
Let's take a look at a simple class-based example:
|
||||
|
||||
```ts
|
||||
class Greeter {
|
||||
greeting: string;
|
||||
constructor(message: string) {
|
||||
this.greeting = message;
|
||||
}
|
||||
greet() {
|
||||
return "Hello, " + this.greeting;
|
||||
}
|
||||
}
|
||||
|
||||
let greeter = new Greeter("world");
|
||||
```
|
||||
|
||||
We declare a new class `Greeter`. This class has three members: a property called `greeting`, a constructor, and a method `greet`.
|
||||
|
||||
You'll notice that in the class when we refer to one of the members of the class we prepend `this.`.
|
||||
This denotes that it's a member access.
|
||||
|
||||
In the last line we construct an instance of the `Greeter` class using `new`.
|
||||
This calls into the constructor we defined earlier, creating a new object with the `Greeter` shape, and running the constructor to initialize it.
|
||||
|
||||
# Inheritance
|
||||
|
||||
### ~hint
|
||||
### Inheritance is not supported yet for the micro:bit. Coming soon...
|
||||
### ~
|
||||
|
||||
In TypeScript, we can use common object-oriented patterns.
|
||||
Of course, one of the most fundamental patterns in class-based programming is being able to extend existing classes to create new ones using inheritance.
|
||||
|
||||
Let's take a look at an example:
|
||||
|
||||
```ts
|
||||
class Animal {
|
||||
name: string;
|
||||
constructor(theName: string) { this.name = theName; }
|
||||
move(distanceInMeters: number = 0) {
|
||||
console.log(`${this.name} moved ${distanceInMeters}m.`);
|
||||
}
|
||||
}
|
||||
|
||||
class Snake extends Animal {
|
||||
constructor(name: string) { super(name); }
|
||||
move(distanceInMeters = 5) {
|
||||
console.log("Slithering...");
|
||||
super.move(distanceInMeters);
|
||||
}
|
||||
}
|
||||
|
||||
class Horse extends Animal {
|
||||
constructor(name: string) { super(name); }
|
||||
move(distanceInMeters = 45) {
|
||||
console.log("Galloping...");
|
||||
super.move(distanceInMeters);
|
||||
}
|
||||
}
|
||||
|
||||
let sam = new Snake("Sammy the Python");
|
||||
let tom: Animal = new Horse("Tommy the Palomino");
|
||||
|
||||
sam.move();
|
||||
tom.move(34);
|
||||
```
|
||||
|
||||
This example covers quite a few of the inheritance features in TypeScript that are common to other languages.
|
||||
Here we see the `extends` keywords used to create a subclass.
|
||||
You can see this where `Horse` and `Snake` subclass the base class `Animal` and gain access to its features.
|
||||
|
||||
Derived classes that contain constructor functions must call `super()` which will execute the constructor function on the base class.
|
||||
|
||||
The example also shows how to override methods in the base class with methods that are specialized for the subclass.
|
||||
Here both `Snake` and `Horse` create a `move` method that overrides the `move` from `Animal`, giving it functionality specific to each class.
|
||||
Note that even though `tom` is declared as an `Animal`, since its value is a `Horse`, when `tom.move(34)` calls the overriding method in `Horse`:
|
||||
|
||||
```Text
|
||||
Slithering...
|
||||
Sammy the Python moved 5m.
|
||||
Galloping...
|
||||
Tommy the Palomino moved 34m.
|
||||
```
|
||||
|
||||
# Public, private, and protected modifiers
|
||||
|
||||
## Public by default
|
||||
|
||||
In our examples, we've been able to freely access the members that we declared throughout our programs.
|
||||
If you're familiar with classes in other languages, you may have noticed in the above examples
|
||||
we haven't had to use the word `public` to accomplish this; for instance,
|
||||
C# requires that each member be explicitly labeled `public` to be visible.
|
||||
In TypeScript, each member is `public` by default.
|
||||
|
||||
You may still mark a member `public` explicitly.
|
||||
We could have written the `Animal` class from the previous section in the following way:
|
||||
|
||||
```ts
|
||||
class Animal {
|
||||
public name: string;
|
||||
public constructor(theName: string) { this.name = theName; }
|
||||
public move(distanceInMeters: number) {
|
||||
console.log(`${this.name} moved ${distanceInMeters}m.`);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Understanding `private`
|
||||
|
||||
When a member is marked `private`, it cannot be accessed from outside of its containing class. For example:
|
||||
|
||||
```ts
|
||||
class Animal {
|
||||
private name: string;
|
||||
constructor(theName: string) { this.name = theName; }
|
||||
}
|
||||
|
||||
new Animal("Cat").name; // Error: 'name' is private;
|
||||
```
|
||||
|
||||
TypeScript is a structural type system.
|
||||
When we compare two different types, regardless of where they came from, if the types of all members are compatible, then we say the types themselves are compatible.
|
||||
|
||||
However, when comparing types that have `private` and `protected` members, we treat these types differently.
|
||||
For two types to be considered compatible, if one of them has a `private` member,
|
||||
then the other must have a `private` member that originated in the same declaration.
|
||||
The same applies to `protected` members.
|
||||
|
||||
Let's look at an example to better see how this plays out in practice:
|
||||
|
||||
```ts
|
||||
class Animal {
|
||||
private name: string;
|
||||
constructor(theName: string) { this.name = theName; }
|
||||
}
|
||||
|
||||
class Rhino extends Animal {
|
||||
constructor() { super("Rhino"); }
|
||||
}
|
||||
|
||||
class Employee {
|
||||
private name: string;
|
||||
constructor(theName: string) { this.name = theName; }
|
||||
}
|
||||
|
||||
let animal = new Animal("Goat");
|
||||
let rhino = new Rhino();
|
||||
let employee = new Employee("Bob");
|
||||
|
||||
animal = rhino;
|
||||
animal = employee; // Error: 'Animal' and 'Employee' are not compatible
|
||||
```
|
||||
|
||||
In this example, we have an `Animal` and a `Rhino`, with `Rhino` being a subclass of `Animal`.
|
||||
We also have a new class `Employee` that looks identical to `Animal` in terms of shape.
|
||||
We create some instances of these classes and then try to assign them to each other to see what will happen.
|
||||
Because `Animal` and `Rhino` share the `private` side of their shape from the same declaration of
|
||||
`private name: string` in `Animal`, they are compatible. However, this is not the case for `Employee`.
|
||||
When we try to assign from an `Employee` to `Animal` we get an error that these types are not compatible.
|
||||
Even though `Employee` also has a `private` member called `name`, it's not the one we declared in `Animal`.
|
||||
|
||||
## Understanding `protected`
|
||||
|
||||
The `protected` modifier acts much like the `private` modifier with the exception that members
|
||||
declared `protected` can also be accessed by instances of deriving classes. For example,
|
||||
|
||||
```ts
|
||||
class Person {
|
||||
protected name: string;
|
||||
constructor(name: string) { this.name = name; }
|
||||
}
|
||||
|
||||
class Employee extends Person {
|
||||
private department: string;
|
||||
|
||||
constructor(name: string, department: string) {
|
||||
super(name);
|
||||
this.department = department;
|
||||
}
|
||||
|
||||
public getElevatorPitch() {
|
||||
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
|
||||
}
|
||||
}
|
||||
|
||||
let howard = new Employee("Howard", "Sales");
|
||||
console.log(howard.getElevatorPitch());
|
||||
console.log(howard.name); // error
|
||||
```
|
||||
|
||||
Notice that while we can't use `name` from outside of `Person`,
|
||||
we can still use it from within an instance method of `Employee` because `Employee` derives from `Person`.
|
||||
|
||||
A constructor may also be marked `protected`.
|
||||
This means that the class cannot be instantiated outside of its containing class, but can be extended. For example,
|
||||
|
||||
```ts
|
||||
class Person {
|
||||
protected name: string;
|
||||
protected constructor(theName: string) { this.name = theName; }
|
||||
}
|
||||
|
||||
// Employee can extend Person
|
||||
class Employee extends Person {
|
||||
private department: string;
|
||||
|
||||
constructor(name: string, department: string) {
|
||||
super(name);
|
||||
this.department = department;
|
||||
}
|
||||
|
||||
public getElevatorPitch() {
|
||||
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
|
||||
}
|
||||
}
|
||||
|
||||
let howard = new Employee("Howard", "Sales");
|
||||
let john = new Person("John"); // Error: The 'Person' constructor is protected
|
||||
```
|
||||
|
||||
# Readonly modifier
|
||||
|
||||
You can make properties readonly by using the `readonly` keyword.
|
||||
Readonly properties must be initialized at their declaration or in the constructor.
|
||||
|
||||
```ts
|
||||
class Octopus {
|
||||
readonly name: string;
|
||||
readonly numberOfLegs: number = 8;
|
||||
constructor (theName: string) {
|
||||
this.name = theName;
|
||||
}
|
||||
}
|
||||
let dad = new Octopus("Man with the 8 strong legs");
|
||||
dad.name = "Man with the 3-piece suit"; // error! name is readonly.
|
||||
```
|
||||
|
||||
## Parameter properties
|
||||
|
||||
In our last example, we had to declare a readonly member `name` and a constructor parameter `theName` in the `Octopus` class, and we then immediately set `name` to `theName`.
|
||||
This turns out to be a very common practice.
|
||||
*Parameter properties* let you create and initialize a member in one place.
|
||||
Here's a further revision of the previous `Octopus` class using a parameter property:
|
||||
|
||||
```ts
|
||||
class Octopus {
|
||||
readonly numberOfLegs: number = 8;
|
||||
constructor(readonly name: string) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Notice how we dropped `theName` altogether and just use the shortened `readonly name: string` parameter on the constructor to create and initialize the `name` member.
|
||||
We've consolidated the declarations and assignment into one location.
|
||||
|
||||
Parameter properties are declared by prefixing a constructor parameter with an accessibility modifier or `readonly`, or both.
|
||||
Using `private` for a parameter property declares and initializes a private member; likewise, the same is done for `public`, `protected`, and `readonly`.
|
||||
|
58
docs/js/faq.md
Normal file
@ -0,0 +1,58 @@
|
||||
# Frequently asked questions
|
||||
|
||||
# What is the language supported for the micro:bit?
|
||||
|
||||
For the micro:bit, we support a "static" subset of TypeScript (itself a superset of JavaScript):
|
||||
|
||||
## Supported language features
|
||||
|
||||
* variables with `let`, `const`, and `var`
|
||||
* functions with lexical scoping and recursion
|
||||
* top-level code in the file; hello world really is `console.log("Hello world")`
|
||||
* `if ... else if ... else` statements
|
||||
* `while` and `do ... while` loops
|
||||
* `for(;;)` loops (see below about `for ... in/of`)
|
||||
* `break/continue`; also with labeled loops
|
||||
* `switch` statement (on numbers only)
|
||||
* `debugger` statement for breakpoints
|
||||
* conditional operator `? :`; lazy boolean operators
|
||||
* namespaces (a form of modules)
|
||||
* all arithmetic operators (including bitwise operators); note that in microcontroller targets
|
||||
all arithmetic is performed on integers, also when simulating in the browser
|
||||
* strings (with a few common methods)
|
||||
* [string templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) (`` `x is ${x}` ``)
|
||||
* arrow functions `() => ...`
|
||||
* classes with fields, methods and constructors; `new` keyword
|
||||
* array literals `[1, 2, 3]`
|
||||
* enums
|
||||
|
||||
## Unsupported language features
|
||||
|
||||
We generally stay away from the more dynamic parts of JavaScript.
|
||||
Things you may miss and we may implement:
|
||||
|
||||
* exceptions (`throw`, `try ... catch`, `try ... finally`)
|
||||
* `for ... of` statements
|
||||
* object literals `{ foo: 1, bar: "two" }`
|
||||
* method-like properties (get/set accessors)
|
||||
* class inheritance
|
||||
|
||||
For JS-only targets we may implement the following:
|
||||
|
||||
* regular expressions
|
||||
* classes implementing interfaces
|
||||
|
||||
Things that we are not very likely to implement:
|
||||
|
||||
* file-based modules (`import * from ...`, `module.exports` etc); we do support namespaces
|
||||
* spread operator
|
||||
* `yield` expression and ``function*``
|
||||
* `await` expression and `async function`
|
||||
* `typeof` expression
|
||||
* tagged templates ``tag `text ${expression} more text` ``; regular templates are supported
|
||||
* binding with arrays or objects: `let [a, b] = ...; let { x, y } = ...`
|
||||
* `with` statement
|
||||
* `eval`
|
||||
* `delete` statement
|
||||
* `for ... in` statements
|
||||
* JSX (HTML as part of JavaScript)
|
161
docs/js/functions.md
Normal file
@ -0,0 +1,161 @@
|
||||
# Functions
|
||||
|
||||
Functions are the fundamental building block of programs. Here is the simplest
|
||||
way to make a function that adds two numbers:
|
||||
|
||||
```ts
|
||||
// Named function
|
||||
function add(x : number, y : number) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
basic.showNumber(add(1, 2))
|
||||
```
|
||||
|
||||
### ~ hint
|
||||
For the micro:bit, you must specify a [type](/js/types) for each function parameter.
|
||||
### ~
|
||||
|
||||
Functions can refer to variables outside of the function body.
|
||||
When they do so, they're said to `capture` these variables.
|
||||
|
||||
```ts
|
||||
let z = 100;
|
||||
|
||||
function addToZ(x: number, y: number) {
|
||||
return x + y + z;
|
||||
}
|
||||
|
||||
basic.showNumber(addToZ(1, 2))
|
||||
```
|
||||
|
||||
## Typing the function
|
||||
|
||||
Let's add a return type to our add function:
|
||||
|
||||
```ts
|
||||
function add(x: number, y: number): number {
|
||||
return x + y;
|
||||
}
|
||||
```
|
||||
|
||||
TypeScript can figure the return type out by looking at the return statements, so you can optionally leave this off in many cases.
|
||||
|
||||
# Optional and Default Parameters
|
||||
|
||||
In TypeScript, the number of arguments given to a function has to match the number of parameters the function expects.
|
||||
|
||||
```ts
|
||||
function buildName(firstName: string, lastName: string) {
|
||||
return firstName + " " + lastName;
|
||||
}
|
||||
|
||||
let result1 = buildName("Bob"); // error, too few parameters
|
||||
let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
|
||||
let result3 = buildName("Bob", "Adams"); // ah, just right
|
||||
```
|
||||
|
||||
In JavaScript, every parameter is optional, and users may leave them off as they see fit.
|
||||
When they do, their value is `undefined`.
|
||||
We can get this functionality in TypeScript by adding a `?` to the end of parameters we want to be optional.
|
||||
For example, let's say we want the last name parameter from above to be optional:
|
||||
|
||||
```ts
|
||||
function buildName(firstName: string, lastName?: string) {
|
||||
if (lastName)
|
||||
return firstName + " " + lastName;
|
||||
else
|
||||
return firstName;
|
||||
}
|
||||
|
||||
let result1 = buildName("Bob"); // works correctly now
|
||||
let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
|
||||
let result3 = buildName("Bob", "Adams"); // ah, just right
|
||||
```
|
||||
|
||||
Any optional parameters must follow required parameters.
|
||||
Had we wanted to make the first name optional rather than the last name, we would need to change the order of parameters in the function, putting the first name last in the list.
|
||||
|
||||
In TypeScript, we can also set a value that a parameter will be assigned if the user does not provide one, or if the user passes `undefined` in its place.
|
||||
These are called default-initialized parameters.
|
||||
Let's take the previous example and default the last name to `"Smith"`.
|
||||
|
||||
```ts
|
||||
function buildName(firstName: string, lastName = "Smith") {
|
||||
return firstName + " " + lastName;
|
||||
}
|
||||
|
||||
let result1 = buildName("Bob"); // works correctly now, returns "Bob Smith"
|
||||
let result2 = buildName("Bob", undefined); // still works, also returns "Bob Smith"
|
||||
let result3 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
|
||||
let result4 = buildName("Bob", "Adams"); // ah, just right
|
||||
```
|
||||
|
||||
Default-initialized parameters that come after all required parameters are treated as optional, and just like optional parameters, can be omitted when calling their respective function.
|
||||
This means optional parameters and trailing default parameters will share commonality in their types, so both
|
||||
|
||||
```ts
|
||||
function buildName(firstName: string, lastName?: string) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
and
|
||||
|
||||
```ts
|
||||
function buildName(firstName: string, lastName = "Smith") {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
share the same type `(firstName: string, lastName?: string) => string`.
|
||||
The default value of `lastName` disappears in the type, only leaving behind the fact that the parameter is optional.
|
||||
|
||||
Unlike plain optional parameters, default-initialized parameters don't *need* to occur after required parameters.
|
||||
If a default-initialized parameter comes before a required parameter, users need to explicitly pass `undefined` to get the default initialized value.
|
||||
For example, we could write our last example with only a default initializer on `firstName`:
|
||||
|
||||
```ts
|
||||
function buildName(firstName = "Will", lastName: string) {
|
||||
return firstName + " " + lastName;
|
||||
}
|
||||
|
||||
let result1 = buildName("Bob"); // error, too few parameters
|
||||
let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
|
||||
let result3 = buildName("Bob", "Adams"); // okay and returns "Bob Adams"
|
||||
let result4 = buildName(undefined, "Adams"); // okay and returns "Will Adams"
|
||||
```
|
||||
|
||||
# Rest Parameters
|
||||
|
||||
Required, optional, and default parameters all have one thing in common: they talk about one parameter at a time.
|
||||
Sometimes, you want to work with multiple parameters as a group, or you may not know how many parameters a function will ultimately take.
|
||||
In JavaScript, you can work with the arguments directly using the `arguments` variable that is visible inside every function body.
|
||||
|
||||
In TypeScript, you can gather these arguments together into a variable:
|
||||
|
||||
```ts
|
||||
function buildName(firstName: string, ...restOfName: string[]) {
|
||||
return firstName + " " + restOfName.join(" ");
|
||||
}
|
||||
|
||||
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
|
||||
```
|
||||
|
||||
*Rest parameters* are treated as a boundless number of optional parameters.
|
||||
When passing arguments for a rest parameter, you can use as many as you want; you can even pass none.
|
||||
The compiler will build an array of the arguments passed in with the name given after the ellipsis (`...`), allowing you to use it in your function.
|
||||
|
||||
The ellipsis is also used in the type of the function with rest parameters:
|
||||
|
||||
```ts
|
||||
function buildName(firstName: string, ...restOfName: string[]) {
|
||||
return firstName + " " + restOfName.join(" ");
|
||||
}
|
||||
|
||||
let buildNameFun: (fname: string, ...rest: string[]) => string = buildName;
|
||||
```
|
||||
|
||||
### ~button /js/types
|
||||
NEXT: Types
|
||||
### ~
|
0
docs/js/inference.md
Normal file
30
docs/js/operators.md
Normal file
@ -0,0 +1,30 @@
|
||||
## Operators
|
||||
|
||||
The following JavaScript operators are supported for the micro:bit.
|
||||
|
||||
### ~hint
|
||||
Note that for the micro:bit all arithmetic is performed on integers, rather than floating point.
|
||||
This also is true when simulating in the browser.
|
||||
### ~
|
||||
|
||||
# Assignment, arithmetic and bitwise
|
||||
|
||||
* assignment operators - [read more](http://devdocs.io/javascript/operators/assignment_operators)
|
||||
* arithmetic operators - [read more](http://devdocs.io/javascript/operators/arithmetic_operators)
|
||||
* bitwise operators - [read more](http://devdocs.io/javascript/operators/bitwise_operators)
|
||||
|
||||
# Comparision and conditional
|
||||
|
||||
* comparison operators - [read more](http://devdocs.io/javascript/operators/comparison_operators)
|
||||
* conditional operator - [read more](http://devdocs.io/javascript/operators/conditional_operator)
|
||||
|
||||
## More
|
||||
|
||||
* lambda functions `() => { ... }`
|
||||
* array literals `[1, 2, 3]`
|
||||
* strings, with a few common methods
|
||||
* [string templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) (`` `x is ${x}` ``)
|
||||
|
||||
### ~button /js/statements
|
||||
NEXT: Statements
|
||||
### ~
|
63
docs/js/sequence.md
Normal file
@ -0,0 +1,63 @@
|
||||
# Sequencing
|
||||
|
||||
By calling one function after another, in sequence, you can create an animation:
|
||||
|
||||
```typescript
|
||||
basic.showLeds(`
|
||||
. # . # .
|
||||
. . . . .
|
||||
. . # . .
|
||||
# . . . #
|
||||
. # # # .
|
||||
`);
|
||||
basic.showLeds(`
|
||||
. # . # .
|
||||
. . . . .
|
||||
. . . . .
|
||||
. # # # .
|
||||
# . . . #
|
||||
`);
|
||||
```
|
||||
|
||||
### The semicolon
|
||||
|
||||
In JavaScript, the semicolon (;) is used to terminate (or end) a statement. However, in most
|
||||
cases, the semicolon is optional and can be omitted. So both code sequences below are
|
||||
legal:
|
||||
|
||||
```typescript
|
||||
basic.showNumber(1)
|
||||
basic.showNumber(2)
|
||||
```
|
||||
|
||||
```typescript
|
||||
basic.showNumber(1);
|
||||
basic.showNumber(2);
|
||||
```
|
||||
|
||||
### The empty statement
|
||||
|
||||
In JavaScript, there is the concept of an *empty statement*, which is whitespace followed by
|
||||
a semicolon in the context where a statement is expected.
|
||||
So, the following code is an infinite loop
|
||||
followed by a call to `showNumber` that will never execute:
|
||||
```typescript
|
||||
while(true) ;
|
||||
basic.showNumber(1);
|
||||
```
|
||||
|
||||
|
||||
### ~hint
|
||||
For the micro:bit, we don't allow a program to contain an empty statement, such as shown above.
|
||||
If you really want an empty statement, you need to use curly braces to delimit an empty statement block:
|
||||
```typescript
|
||||
while(true) { }
|
||||
basic.showNumber(1);
|
||||
```
|
||||
### ~
|
||||
|
||||
[Read more](http://inimino.org/~inimino/blog/javascript_semicolons) about semicolons in JavaScript.
|
||||
|
||||
### ~button /js/variables
|
||||
NEXT: Variable Declarations
|
||||
### ~
|
33
docs/js/statements.md
Normal file
@ -0,0 +1,33 @@
|
||||
# Statements
|
||||
|
||||
The following JavaScript statements are supported for the micro:bit:
|
||||
|
||||
## Variable declarations
|
||||
* `const` statement - [read more](http://devdocs.io/javascript/statements/const)
|
||||
* `let` statement - [read more](http://devdocs.io/javascript/statements/let)
|
||||
* `var` statement - [read more](http://devdocs.io/javascript/statements/var)
|
||||
|
||||
## Block-structured statements
|
||||
|
||||
* `{ }` block statement - [read more](http://devdocs.io/javascript/statements/block)
|
||||
* `if-else` conditional statement - [read more](http://devdocs.io/javascript/statements/if...else)
|
||||
* `while` loop - [read more](http://devdocs.io/javascript/statements/do...while)
|
||||
* `do-while` loop - [read more](http://devdocs.io/javascript/statements/do...while)
|
||||
* `for(;;)` loop - [read more](http://devdocs.io/javascript/statements/for)
|
||||
* `switch` statement (on numbers only) - [read more](http://devdocs.io/javascript/statements/switch)
|
||||
|
||||
## Control-flow commands
|
||||
|
||||
* `break` statement - [read more](http://devdocs.io/javascript/statements/break)
|
||||
* `continue` statement - [read more](http://devdocs.io/javascript/statements/continue)
|
||||
* `return` statement - [read more](http://devdocs.io/javascript/statements/return)
|
||||
* `debugger` statement for breakpoints - [read more](http://devdocs.io/javascript/statements/debugger)
|
||||
|
||||
## Labelling statements
|
||||
|
||||
* labelled statement - [read more](http://devdocs.io/javascript/statements/label)
|
||||
* `default` statement - [read more](http://devdocs.io/javascript/statements/default)
|
||||
|
||||
### ~button /js/functions
|
||||
NEXT: Functions
|
||||
### ~
|
140
docs/js/types.md
Normal file
@ -0,0 +1,140 @@
|
||||
# Types
|
||||
|
||||
For programs to be useful, we need to be able to work with some of the simplest units of data:
|
||||
numbers, strings, structures, boolean values, and the like.
|
||||
|
||||
# Boolean
|
||||
|
||||
The most basic datatype is the simple true/false value, which is called a `boolean` value.
|
||||
|
||||
```ts
|
||||
let isDone: boolean = false;
|
||||
```
|
||||
|
||||
# Number
|
||||
|
||||
### ~ hint
|
||||
In JavaScript, `numbers` are floating point values.
|
||||
However, for the micro:bit, `numbers` are integer values.
|
||||
### ~
|
||||
|
||||
Integer values can be specified via decimal, hexadecimal and octal notation:
|
||||
|
||||
```ts
|
||||
let decimal: number = 42;
|
||||
let hex: number = 0xf00d;
|
||||
let binary: number = 0b1010;
|
||||
let octal: number = 0o744;
|
||||
```
|
||||
|
||||
# String
|
||||
|
||||
As in other languages, we use the type `string` to refer to textual data.
|
||||
Use double quotes (`"`) or single quotes (`'`) to surround string data.
|
||||
|
||||
```ts
|
||||
let color: string = "blue";
|
||||
color = 'red';
|
||||
```
|
||||
|
||||
You can also use *template strings*, which can span multiple lines and have embedded expressions.
|
||||
These strings are surrounded by the backtick/backquote (`` ` ``) character, and embedded expressions are of the form `${ expr }`.
|
||||
|
||||
```ts
|
||||
let fullName: string = `Bob Bobbington`;
|
||||
let age: number = 37;
|
||||
let sentence: string = `Hello, my name is ${ fullName }.
|
||||
|
||||
I'll be ${ age + 1 } years old next month.`
|
||||
```
|
||||
|
||||
This is equivalent to declaring `sentence` like so:
|
||||
|
||||
```ts
|
||||
let sentence: string = "Hello, my name is " + fullName + ".\n\n" +
|
||||
"I'll be " + (age + 1) + " years old next month."
|
||||
```
|
||||
|
||||
# Array
|
||||
|
||||
Arrays allow you to work with an expandable sequence of values, addressed by an integer-valued index.
|
||||
Array types can be written in one of two ways.
|
||||
In the first, you use the type of the elements followed by `[]` to denote an array of that element type:
|
||||
|
||||
```ts
|
||||
let list: number[] = [1, 2, 3];
|
||||
```
|
||||
|
||||
The second way uses a generic array type, `Array<elemType>`:
|
||||
|
||||
```ts
|
||||
let list: Array<number> = [1, 2, 3];
|
||||
```
|
||||
|
||||
### ~hint
|
||||
For the micro:bit, all elements of an array must have the same type.
|
||||
### ~
|
||||
|
||||
|
||||
# Enum
|
||||
|
||||
A helpful addition to the standard set of datatypes from JavaScript is the `enum`.
|
||||
As in languages like C#, an enum is a way of giving more friendly names to sets of numeric values.
|
||||
|
||||
```ts
|
||||
enum Color {Red, Green, Blue};
|
||||
let c: Color = Color.Green;
|
||||
```
|
||||
|
||||
By default, enums begin numbering their members starting at `0`.
|
||||
You can change this by manually setting the value of one of its members.
|
||||
For example, we can start the previous example at `1` instead of `0`:
|
||||
|
||||
```ts
|
||||
enum Color {Red = 1, Green, Blue};
|
||||
let c: Color = Color.Green;
|
||||
```
|
||||
|
||||
Or, even manually set all the values in the enum:
|
||||
|
||||
```ts
|
||||
enum Color {Red = 1, Green = 2, Blue = 4};
|
||||
let c: Color = Color.Green;
|
||||
```
|
||||
|
||||
# Any
|
||||
|
||||
The TypeScript type `any` is not supported in the micro:bit.
|
||||
|
||||
|
||||
# Void
|
||||
|
||||
`void` is the absence of having any type at all.
|
||||
You may commonly see this as the return type of functions that do not return a value:
|
||||
|
||||
```ts
|
||||
function warnUser(): void {
|
||||
basic.showString("This is my warning message");
|
||||
}
|
||||
```
|
||||
|
||||
Declaring variables of type `void` is not useful.
|
||||
|
||||
# Type Inference
|
||||
|
||||
In TypeScript, there are several places where type inference is used to provide type information when there is
|
||||
no explicit type annotation. For example, in this code
|
||||
|
||||
```ts
|
||||
let x = 3;
|
||||
let y = x + 3
|
||||
```
|
||||
|
||||
The type of the `x` variable is inferred to be `number`. Similarly, the type of `y` variable also is inferred to be `number`.
|
||||
This kind of inference takes place when initializing variables and members,
|
||||
setting parameter default values, and determining function return types.
|
||||
|
||||
|
||||
### ~button /js/classes
|
||||
NEXT: Classes
|
||||
### ~
|
121
docs/js/variables.md
Normal file
@ -0,0 +1,121 @@
|
||||
# Variable Declarations
|
||||
|
||||
Declaring a variable in JavaScript has always traditionally been done with the `var` keyword.
|
||||
|
||||
```typescript
|
||||
var a = 10;
|
||||
```
|
||||
|
||||
The `var` construct has some [problems](http://www.typescriptlang.org/docs/handbook/variable-declarations.html),
|
||||
which is why `let` statements were introduced. Apart from the keyword used, `let` statements are written
|
||||
the same way `var` statements are.
|
||||
|
||||
```typescript
|
||||
let a = 10;
|
||||
```
|
||||
|
||||
The key difference is not in the syntax, but in the semantics, which we'll now dive into.
|
||||
|
||||
## Block-scoping
|
||||
|
||||
When a variable is declared using `let`, it uses what some call *lexical-scoping* or *block-scoping*.
|
||||
Unlike variables declared with `var` whose scopes leak out to their containing function,
|
||||
block-scoped variables are not visible outside of their nearest containing block or `for`-loop.
|
||||
|
||||
```typescript
|
||||
function f(input: boolean) {
|
||||
let a = 100;
|
||||
|
||||
if (input) {
|
||||
// Still okay to reference 'a'
|
||||
let b = a + 1;
|
||||
return b;
|
||||
}
|
||||
|
||||
// Error: 'b' doesn't exist here
|
||||
return b;
|
||||
}
|
||||
```
|
||||
|
||||
Here, we have two local variables `a` and `b`.
|
||||
`a`'s scope is limited to the body of `f` while `b`'s scope is limited to the containing `if` statement's block.
|
||||
|
||||
Another property of block-scoped variables is that they can't be read or written to before they're actually declared.
|
||||
While these variables are "present" throughout their scope, all points up until their declaration are part of their *temporal dead zone*.
|
||||
This is just a sophisticated way of saying you can't access them before the `let` statement, and luckily TypeScript will let you know that.
|
||||
|
||||
```typescript
|
||||
a++; // illegal to use 'a' before it's declared;
|
||||
let a;
|
||||
```
|
||||
|
||||
## Re-declarations
|
||||
|
||||
With `var` declarations, it doesn't matter how many times you declare your variables, you just get one:
|
||||
|
||||
```typescript
|
||||
var x = 10;
|
||||
var x = 20;
|
||||
```
|
||||
|
||||
In the above example, all declarations of `x` actually refer to the *same* `x`, and this is perfectly valid.
|
||||
This often ends up being a source of bugs. Thankfully, `let` declarations are not as forgiving.
|
||||
|
||||
```typescript
|
||||
let x = 10;
|
||||
let x = 20; // error: can't re-declare 'x' in the same scope
|
||||
```
|
||||
|
||||
## Shadowing
|
||||
|
||||
The act of introducing a new name in a more deeply nested scope is called *shadowing*.
|
||||
It is a bit of a double-edged sword in that it can introduce certain bugs on its own in the
|
||||
event of accidental shadowing, while also preventing certain bugs.
|
||||
For instance, imagine a `sumMatrix` function using `let` variables.
|
||||
|
||||
```typescript
|
||||
function sumMatrix(matrix: number[][]) {
|
||||
let sum = 0;
|
||||
for (let i = 0; i < matrix.length; i++) {
|
||||
var currentRow = matrix[i];
|
||||
for (let i = 0; i < currentRow.length; i++) {
|
||||
sum += currentRow[i];
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
```
|
||||
|
||||
This version of the loop will actually perform the summation correctly because the inner loop's `i` shadows `i` from the outer loop.
|
||||
Shadowing should *usually* be avoided in the interest of write clearer code, such as
|
||||
|
||||
```typescript
|
||||
function sumMatrix(matrix: number[][]) {
|
||||
let sum = 0;
|
||||
for (let i = 0; i < matrix.length; i++) {
|
||||
var currentRow = matrix[i];
|
||||
for (let j = 0; j < currentRow.length; j++) {
|
||||
sum += currentRow[j];
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
```
|
||||
While there are some scenarios where it may be fitting to take advantage of it, you should use your best judgement.
|
||||
|
||||
# `const` declarations
|
||||
|
||||
`const` declarations are another way of declaring variables.
|
||||
|
||||
```typescript
|
||||
const numLivesForCat = 9;
|
||||
```
|
||||
|
||||
They are like `let` declarations but, as their name implies, their value cannot be changed once they are bound.
|
||||
In other words, they have the same scoping rules as `let`, but you can't re-assign to them.
|
||||
|
||||
### ~button /js/operators
|
||||
NEXT: Operators
|
||||
### ~
|
@ -41,7 +41,7 @@ Now let's add some more types of instructions for the player to follow. Let's ad
|
||||
/**
|
||||
* {highlight}
|
||||
*/
|
||||
export function newAction_() {
|
||||
export function newAction() {
|
||||
action = Math.random(4) // ***
|
||||
if (action == 0) {
|
||||
basic.showString("PUSH A", 150) // ***
|
||||
|
@ -7,7 +7,7 @@ Measure the acceleration on the micro:bit in the "x" direction.
|
||||
|
||||
## Directions
|
||||
|
||||
Use this activity document to guide your work in the [glowing pendulum activity](/lessons/charting/acceleration)
|
||||
Use this activity document to guide your work in the [charting activity](/lessons/charting)
|
||||
|
||||
Answer the questions while completing the tutorial. Pay attention to the dialogues!
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
Your beginning code should look like this:
|
||||
|
||||
```blocks
|
||||
let coll = (<string[]>[])
|
||||
let coll: string[] = []
|
||||
coll.push("puppy")
|
||||
coll.push("clock")
|
||||
coll.push("night")
|
||||
@ -27,7 +27,7 @@ game.startCountdown(30000)
|
||||
Let's add more words for the player to act out! But first, we need to increase the time in one round to give the player more time get through all the words. Let's change the `game->start countdown` statement.
|
||||
|
||||
```blocks
|
||||
let coll = (<string[]>[])
|
||||
let coll: string[] = []
|
||||
coll.push("puppy")
|
||||
coll.push("clock")
|
||||
coll.push("night")
|
||||
@ -52,7 +52,8 @@ game.startCountdown(60000)
|
||||
Now let's add 5 more words to our list of charade words. Right above the the line `word:=coll->at(index)` add 5 lines that say `coll->add("")`. In this example, we will add the words **bicycle, telephone, sun, car, and ant** but you can add whatever words you like.
|
||||
|
||||
```blocks
|
||||
let coll.push("puppy")
|
||||
let coll: string[] = []
|
||||
coll.push("puppy")
|
||||
coll.push("clock")
|
||||
coll.push("night")
|
||||
coll.push("cat")
|
||||
|