Compare commits

...

74 Commits

Author SHA1 Message Date
0a746f5bbe 0.3.78 2016-09-06 20:41:04 -07:00
066408c317 Bump pxt-core to 0.3.92 2016-09-06 20:41:02 -07:00
90f7b229d1 0.3.77 2016-09-06 13:41:41 -07:00
c54e0b0e9d Bump pxt-core to 0.3.90 2016-09-06 13:41:35 -07:00
ea088ac828 renaming docs image files 2016-09-06 13:31:47 -07:00
29cf4d3e53 uses croc clips in instructions only for micro:bit 2016-09-06 10:52:22 -07:00
6d637eefd7 scaling, cropping,blurring 2016-09-06 10:06:09 -07:00
6310e96ac2 Merge pull request #239 from Microsoft/usb-docs-update
.hex file download and USB transfer docs update
2016-09-06 09:10:06 -07:00
dbb1e31822 Remove DS_STORE 2016-09-06 10:01:12 +01:00
5376bc2dce Rename images, remove redundant images 2016-09-06 09:57:45 +01:00
57bd293df8 Move arrow position on doc image 2016-09-06 09:52:17 +01:00
e570d46755 Rewrite instructions on downloading files to make them more clear 2016-09-06 09:49:08 +01:00
d37f284fce Added arrows to images and updated instructions 2016-09-06 09:28:20 +01:00
b716226889 Images for Windows 2016-09-06 09:05:33 +01:00
1bd19cc1a0 support list micro:bit on linux 2016-09-06 00:12:57 -07:00
ac8c9c5e85 Updating editor screenshots in js/cal, fixes #230 2016-09-05 09:04:03 -07:00
057260c483 Update OS X Firefox screenshots and instructions 2016-09-05 16:46:56 +01:00
568ae32f81 Update screenshot and instructions for OS X Chrome 2016-09-05 16:32:41 +01:00
ae605ff829 Update OS X file transfer screenshot 2016-09-05 16:22:06 +01:00
f25ddb1085 OS X screenshot 2016-09-05 15:50:27 +01:00
f175f973f0 0.3.76 2016-09-05 14:26:24 +01:00
c7e5fa490e Bump pxt-core to 0.3.87 2016-09-05 14:26:24 +01:00
61a29f7c67 Always diplay sad face on errors; use nullCheck() function; see https://github.com/Microsoft/pxt/issues/302 2016-09-05 14:26:07 +01:00
50293fc654 don't repace spaces 2016-09-02 21:38:22 -07:00
a9ecadaf09 Merge pull request #238 from Microsoft/power-usage
Direct power wires for single usages
2016-09-02 21:13:15 -07:00
6e56107eb5 Merge branch 'master' into power-usage 2016-09-02 16:12:48 -07:00
1f077beb65 directly wires power if there is single usage 2016-09-02 16:11:58 -07:00
8fff762156 removed uwp info 2016-09-02 16:08:49 -07:00
cebded2526 Merge pull request #237 from Microsoft/power-usage
finer grain power wires based on usage
2016-09-02 16:07:02 -07:00
13f53d730a fixes instruction steps for finer power usage 2016-09-02 15:43:26 -07:00
8adcab1cab finer grain power wires based on usage 2016-09-02 15:24:16 -07:00
8cb5f442f9 0.3.75 2016-09-02 12:07:49 -07:00
96448d5237 Bump pxt-core to 0.3.86 2016-09-02 12:07:34 -07:00
30f01bb0ac 0.3.74 2016-09-02 17:32:54 +01:00
3d0b397de2 Bump pxt-core to 0.3.85 2016-09-02 17:32:54 +01:00
e0de55d689 Add pxtrt::runtimeWarning() support; see https://github.com/Microsoft/pxt/issues/31 2016-09-02 17:29:40 +01:00
7637a98f07 0.3.73 2016-09-02 16:54:27 +01:00
95f94e0886 Bump pxt-core to 0.3.84 2016-09-02 16:54:26 +01:00
9a2367cf8e Add dummy implementations for some bluetooth functions to avoid crashes 2016-09-02 16:03:55 +01:00
15fecb77c4 0.3.72 2016-09-01 23:23:16 -07:00
4f69bbabfb Bump pxt-core to 0.3.82 2016-09-01 23:23:13 -07:00
8351ed0513 Merge pull request #227 from Microsoft/max6675
adds MAX6675; adds general SPI & I2C support to sim
2016-09-01 22:48:33 -07:00
c34b0a1aeb Merge branch 'master' into max6675 2016-09-01 22:48:02 -07:00
9bcd44d7e4 0.3.71 2016-09-01 22:39:31 -07:00
3403da8ce8 Bump pxt-core to 0.3.81 2016-09-01 22:39:27 -07:00
39c146329f perf optimization 2016-09-01 22:18:36 -07:00
8d0d0a7e9a 0.3.70 2016-09-01 22:00:15 -07:00
61b3783dd4 Bump pxt-core to 0.3.80 2016-09-01 22:00:13 -07:00
da16428842 merging master 2016-09-01 21:12:03 -07:00
359c456577 adds full-page instruction printing 2016-09-01 19:07:01 -07:00
b3d9c167e1 0.3.69 2016-09-01 17:13:25 -07:00
78398b220f Bump pxt-core to 0.3.79 2016-09-01 17:13:24 -07:00
a656fbbd7b embedding parts svg files in pxt.json 2016-09-01 16:24:12 -07:00
e681cc8c97 added parts to microbit 2016-09-01 15:37:39 -07:00
03beec9c49 0.3.68 2016-09-01 12:13:07 -07:00
1600644be5 Bump pxt-core to 0.3.77 2016-09-01 12:13:06 -07:00
a3dd64eb4c Merge branch 'master' of https://github.com/Microsoft/pxt-microbit 2016-09-01 12:12:48 -07:00
b865cce44e embedding neopixel / speaker svgs 2016-09-01 10:56:06 -07:00
dc42900c7f merges with master 2016-09-01 10:08:32 -07:00
dcc3bd95fe ignores max6675 2016-09-01 10:07:11 -07:00
61e63831aa 0.3.67 2016-09-01 09:10:49 -07:00
5651c3b9ba Bump pxt-core to 0.3.76 2016-09-01 09:10:44 -07:00
a562557bca Merge branch 'master' of https://github.com/Microsoft/pxt-microbit 2016-09-01 08:59:31 -07:00
d890c05229 moving parts .svg under simulator 2016-09-01 08:57:20 -07:00
4340e1f7ed Rename instructions.html to siminstructions.html; fixes #234 2016-09-01 16:47:32 +01:00
e2e4c68f85 0.3.66 2016-09-01 08:05:39 -07:00
3f6a3089f1 Bump pxt-core to 0.3.75 2016-09-01 08:05:35 -07:00
84a0c0fe56 0.3.65 2016-09-01 06:59:50 -07:00
5237b86cf5 docs cleanup 2016-09-01 06:49:39 -07:00
4070d4e691 Merge branch 'master' into max6675 2016-08-31 22:41:59 -07:00
7048156b46 draws small wires for small micro:bit pins 2016-08-31 22:41:30 -07:00
232758805b removes "debugger" statement 2016-08-31 21:56:46 -07:00
211d4e5538 adds max6675 2016-08-31 21:55:55 -07:00
374d8c590d adds spi and i2c pins 2016-08-31 21:53:48 -07:00
111 changed files with 691 additions and 771 deletions

View File

@ -53,11 +53,6 @@ pxt update
More instructions at https://github.com/Microsoft/pxt#running-a-target-from-localhost
## 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 ``codethemicrobit.com`` and provides additional features.
### Building
* Install Visual Studio 2015 Update 2 or higher. Make sure the Windows 10 templates are installed.

View File

@ -28,7 +28,7 @@ export function deployCoreAsync(res: ts.pxtc.CompileResult) {
function getBitDrivesAsync(): Promise<string[]> {
if (process.platform == "win32") {
let rx = new RegExp("^([A-Z]:).* " + pxt.appTarget.compile.deployDrives)
const rx = new RegExp("^([A-Z]:).* " + pxt.appTarget.compile.deployDrives)
return execAsync("wmic PATH Win32_LogicalDisk get DeviceID, VolumeName, FileSystem")
.then(buf => {
let res: string[] = []
@ -42,9 +42,14 @@ function getBitDrivesAsync(): Promise<string[]> {
})
}
else if (process.platform == "darwin") {
let rx = new RegExp(pxt.appTarget.compile.deployDrives)
const rx = new RegExp(pxt.appTarget.compile.deployDrives)
return readDirAsync("/Volumes")
.then(lst => lst.filter(s => rx.test(s)).map(s => "/Volumes/" + s + "/"))
} else if (process.platform == "linux") {
const rx = new RegExp(pxt.appTarget.compile.deployDrives)
const user = process.env["USER"]
return readDirAsync(`/media/${user}`)
.then(lst => lst.filter(s => rx.test(s)).map(s => `/media/${user}/${s}/`))
} else {
return Promise.resolve([])
}

View File

@ -1,37 +1,36 @@
# Math
[Numeric](/reference/types/number) values: 0, 1, 2, ...
### [Numeric](/reference/types/number) values: 0, 1, 2, ...
```blocks
```block
0;
1;
2;
```
Arithmetic binary operation (+, -, *, /)
### Arithmetic binary operation (+, -, *, /)
```blocks
```block
0+1;
0-1;
1*2;
3/4;
```
Absolute value
### Absolute value
```blocks
```block
Math.abs(-5);
```
Minimum/maximum of two values
### Minimum/maximum of two values
```blocks
```block
Math.min(0, 1);
Math.max(0, 1);
```
Random value
### Random value
```blocks
```block
Math.random(5);
```

View File

@ -1,42 +0,0 @@
# Math functions
### @parent blocks/language
The math library includes math related functions that you can use with [Numbers](/reference/types/number).
### abs
math `->` abs (x : [Number](/reference/types/number)) *returns* [Number](/reference/types/number)
returns the absolute value of input parameter `x`
![](/static/mb/blocks/math-0.png)
### max
math `->` max (x : [Number](/reference/types/number), y : [Number](/reference/types/number)) *returns* [Number](/reference/types/number)
returns the larger of two input numbers (`x` and `y`)
![](/static/mb/blocks/math-1.png)
### min
math `->` min (x : [Number](/reference/types/number), y : [Number](/reference/types/number)) *returns* [Number](/reference/types/number)
returns the smaller of two input numbers (`x` and `y`)
![](/static/mb/blocks/math-2.png)
### random
math `->` random (limit : [Number](/reference/types/number)) *returns* [Number](/reference/types/number)
returns a random [Number](/reference/types/number) between 0 and the parameter *limit*
![](/static/mb/blocks/math-3.png)
### See also
[Number](/reference/types/number)

View File

@ -1,19 +1,24 @@
# Run Scripts on your micro:bit
# Running programs on your micro:bit
How to compile, transfer, and run a script on your micro:bit.
How to compile, transfer, and run a program on your micro:bit.
While you're writing and testing your scripts, you'll mostly be running scripts in your browser by clicking the `PLay` button
(see [run code in your browser](/device/simulator) for info about this).
While you're writing and testing your programs, you'll mostly be [running them
in the simulator](/device/simulator), but once you've finished your program you
can **compile** it and run it on your micro:bit.
Once your masterpiece is complete, you can compile your script and run it on your micro:bit.
The basic steps are:
1. Connect your micro:bit to your computer via USB
2. Click **Download** and download the `.hex` file
3. Copy the `.hex` file from your computer onto the micro:bit drive
## Requirements
You need the following things to transfer and run a script on your micro:bit:
* A-Male to Micro USB cable to connect your computer to your micro:bit. This is the same cable that is commonly used to connect a smart phone to a computer.
* a PC running Windows 7 of later, or a Mac running OS X 10.6 or later
* access to the Internet
* A-Male to Micro USB cable to connect your computer to your micro:bit. This is
the same cable that is commonly used to connect a smart phone to a computer.
* A PC running Windows 7 or later, or a Mac running OS X 10.6 or later
## Step 1: Connect your micro:bit to your computer
@ -23,108 +28,151 @@ First, connect the micro:bit:
2. Connect the other end of the USB cable to a USB port on your computer.
Your computer should recognise your micro:bit as a new drive. On computers running Windows, MICROBIT appears as a drive under Devices and drives. On a Mac it appears as a new drive under Devices.
Your computer should recognise your micro:bit as a new drive. On computers
running Windows, `MICROBIT` appears as a drive under Devices and drives. On a Mac
it appears as a new drive under Devices.
Windows
**Windows**
![](/static/mb/device/usb-0.jpg)
![](/static/mb/device/usb-windows-device.jpg)
Mac (picture bvabdbco)
WARN: unknown picture: bvabdbco:5x3
**Mac**
## Step 2: Compile your script
![](/static/mb/device/usb-osx-device.png)
Next, compile your script:
## Step 2: Download your program
1. Sign in to Touch Develop on your computer.
2. Open your script (find the script in **My Scripts** and click `Edit`).
3. Click **Download**. Your script is converted into a hex file that you can transfer and run on your micro:bit.
4. When prompted, choose to save the compiled file on your computer (or anywhere other than the micro:bit). Depending on which browser you are using, the download will adopt the download behaviour of that particular browser.
1. Open your project on [codethemicrobit.com](https://codethemicrobit.com)
2. Click **Download**
3. When prompted, choose to **save** the compiled file onto your computer. The
prompt will be different depending on which browser you are using, or
whether you are using a Windows computer or a Mac
### Windows
** Chrome**
#### Chrome
Your .hex file appears as a download at the bottom of the browser. Open up your windows file explorer. Your micro:bit appears as a drive called MICROBIT.
Your `.hex` file appears as a download at the bottom of the browser. Click on
the arrow next to the name of the file and then click **Show in folder**.
**Right click** on the download and select **show in folder**. Drag and drop the hex file from the download folder onto the MICROBIT drive.
![](/static/mb/device/usb-windows-chrome.png)
Alternatively, you can drag and drop the downloaded hex file from the bottom of the browser onto the file explorer and onto the MICROBIT drive.
Drag and drop the `.hex` file from the download folder onto the `MICROBIT` drive.
![](/static/mb/device/usb-1.jpg)
#### Firefox
**Firefox**
A window will appear asking whether you want to save or open the `.hex` file.
Select **Save File** and then select **OK**.
A dialogue box will appear, asking whether you would like to open or save your hex file. Select **Save**, then **OK** and the file will appear in your downloads in the top right of your browser. Select the **blue arrow**, select the relevant file and drag and drop it onto your Windows Explorer and onto your MICROBIT drive.
![](/static/mb/device/usb-windows-firefox-1.png)
![](/static/mb/device/usb-2.jpg)
The file will then appear in your downloads in the top right of your browser.
Click the **folder icon** next to the filename to open it in Windows Explorer.
![](/static/mb/device/usb-3.jpg)
![](/static/mb/device/usb-windows-firefox-2.png)
**IE10**
Drag and drop the `.hex` file from the download folder onto the `MICROBIT` drive.
Click on **Download**. You will see a message “Do you want to save this .hex file.” Select **Save**.
#### Microsoft Edge
A message will appear at the bottom of the browser asking what you want to do
with the file. Click **Save**:
![](/static/mb/device/usb-windows-edge-1.png)
Then click **Open folder** and drag and drop the file from your Downloads to
your `MICROBIT` drive.
![](/static/mb/device/usb-windows-edge-2.png)
#### Internet Explorer
A message will appear at the bottom of the browser asking what you want to do
with the file. Click **Save**:
![](/static/mb/device/usb-windows-ie11-1.png)
Then click **Open folder** and drag and drop the file from your Downloads to
your `MICROBIT` drive.
![](/static/mb/device/usb-windows-ie11-2.png)
### Mac
** Safari**
#### Safari
When you select **Download** in Safari on Mac, your file will be downloaded to your downloads folder. Go to your downloads folder and open the file. In Safari the file will appear as unknown.txt rather than a named .hex file. Drag and drop it onto your MICROBIT drive.
When you select **Download** in Safari a file called `Unknown` will be
downloaded into your Downloads folder. Open your Downloads folder and drag and
drop the file onto your `MICROBIT` drive, under Devices:
![](/static/mb/device/usb-4.jpg)
![](/static/mb/device/usb-osx-dnd.png)
**Firefox**
#### Firefox
A dialogue box will appear, asking whether you would like to open or save your hex file. Select **Save** and **OK** and the file will then appear in your downloads in the top right of your browser. Click on **Show in Finder** and the file will appear in your downloads folder. Select the file and drag and drop it onto your MICROBIT drive.
A dialogue box will appear, asking whether you would like to open or save your
hex file. Select **Save file** and click **OK** and the file will then appear in
your downloads in the top right of your browser. Right click on the file and
click on **Show in Finder** and the file will appear in your downloads folder.
Select the file and drag and drop it onto your `MICROBIT` drive.
![](/static/mb/device/usb-5.jpg)
![](/static/mb/device/usb-osx-firefox-1.png)
![](/static/mb/device/usb-6.jpg)
![](/static/mb/device/usb-osx-firefox-2.png)
**Chrome**
#### Chrome
When you select **Download** in Chrome, the file will be downloaded to the bottom of the browser in .hex format. Click on the small arrow and select **Show in Finder**. This will show the file in your download folder. Drag and drop the file onto your MICROBIT drive.
When you select **Download** in Chrome, the file will appear at the bottom of
the browser. Click on the small arrow and select **Show in Finder**. This will
show the file in your download folder. Drag and drop the file onto your
`MICROBIT` drive.
![](/static/mb/device/usb-7.jpg)
![](/static/mb/device/usb-osx-chrome.png)
## Step 3: Transfer the file to your micro:bit
1. The file will transfer onto your micro:bit.
2. If you're using Windows, you can use **Send to** as described below.
3. The LED on the back of your micro:bit flashes during the transfer (which should only take a few seconds).
4. Once transferred, the code will run automatically on your micro:bit. To rerun your program, press the reset button on the back of your micro:bit. The reset button automatically runs the newest file on the micro:bit.
* Once you've found the folder containing your `.hex` file, drag and drop it
onto your `MICROBIT` drive
* If you're using Windows, you can use **Send to** as described below
* The LED on the back of your micro:bit flashes during the transfer (which
should only take a few seconds).
* Once transferred, the code will run automatically on your micro:bit. To rerun
your program, press the reset button on the back of your micro:bit. The reset
button automatically runs the newest file on the micro:bit.
**Send to**: If you're using Windows you use *Send to* in File Explorer:
- In File Explorer, right-click on the hex file (created in Step 2 above), choose **Send to**, and then **MICROBIT**.
![](/static/mb/device/usb-8.jpg)
![](/static/mb/device/usb-windows-sendto.jpg)
By copying the script onto the 'MICROBIT' drive, you have programmed it into the flash memory on the micro:bit, which means even after you unplug the micro:bit, your script will still run if the micro:bit is powered by battery.
By copying the script onto the `MICROBIT` drive, you have programmed it into the
flash memory on the micro:bit, which means even after you unplug the micro:bit,
your program will still run if the micro:bit is powered by battery.
## Troubleshooting
You cant drag and drop more than one hex file at once onto your micro:bit. If you try to drag and drop a second hex file onto your micro:bit before the first file has finished downloading, then the second file may fail in different ways.
You cant drag and drop more than one hex file at once onto your micro:bit. If
you try to drag and drop a second hex file onto your micro:bit before the first
file has finished downloading, then the second file may fail in different ways.
When the first program has been written to the micro:bit, the drive will disengage. If you drag and drop a second file at this point it may not find the drive and the second write will fail.
When the first program has been written to the micro:bit, the drive will
disengage. If you drag and drop a second file at this point it may not find the
drive and the second write will fail.
The errors may look like this:
**Windows**
![](/static/mb/device/usb-9.jpg)
![](/static/mb/device/usb-windows-copy-file-error.jpg)
**Mac**
![](/static/mb/device/usb-10.png)
![](/static/mb/device/usb-osx-copy-file-error.png)
Or it may appear that there are two hex files on your micro:bit so the micro:bit wont be able to run multiple files. To rectify this, unplug your micro:bit and plug it in again. Make sure that your micro:bit appears as MICROBIT and not MAINTENANCE.
Or it may appear that there are two hex files on your micro:bit so the micro:bit
wont be able to run multiple files. To rectify this, unplug your micro:bit and
plug it in again. Make sure that your micro:bit appears as `MICROBIT` and not
`MAINTENANCE`.
### See also

View File

@ -4,9 +4,11 @@ An introduction to conditions for the Block Editor.
## Introduction to conditions
In the introduction to code, we made the BBC micro:bit automatically shows the message hello, world!:
In the introduction to code, we made the BBC micro:bit automatically shows the message hello world!:
![](/static/mb/blocks/lessons/blocks-conditions-0.png)
```blocks
basic.showString("hello world!")
```
This statement, or code, will happen as soon as the BBC micro:bit is activated. This means it is unconditional. We can add a condition to make code function in certain ways:
@ -16,11 +18,13 @@ This statement, or code, will happen as soon as the BBC micro:bit is activated.
In programming we use an if statement: if this condition is met, do something. Lets add an if statement to the code we had before; the BBC Micro:bit will wait for the user to press a button before showing the image.
### Write the code
Click the **if** category and drag an `if/do` block. Drag the`show string` block we wrote previously into the `do` section of the block. Next click the **input** tab and drag a `button pressed` block, connect it to the open jigsaw of the `if` block. This is our criteria: `if A button is pressed`. We can change which button (button A or B) by clicking the arrow next to A and changing the value. This means our BBC micro:bit is waiting for button A (the left button) to be pressed. Finally go to the **basic** tab and drag a `forever` block, and attach all our code inside. We add this block to ensure the BBC micro:bit is always waiting to show us this message, not just once. Your code should look like this:
![](/static/mb/blocks/lessons/blocks-conditions-1.png)
```blocks
basic.forever(() => {
if (input.buttonIsPressed(Button.A)) {
basic.showString("hello world!")
}
})
```
Again, test the code in the simulator. Try clicking **Button A** to display the "hello, world!" message every time the `button is pressed`.
@ -40,7 +44,15 @@ For example, we could make it so our BBC Micro:bit tells us to press the A butto
We want the message "Press A!" to scroll across the BBC micro:bit, so right-click the `show string` block and select **Duplicate**. Drag this new block into the `else` section and replace the “hello, world!” with "Press A!". Your code should look like this:
![](/static/mb/blocks/lessons/blocks-conditions-2.png)
```blocks
basic.forever(() => {
if (input.buttonIsPressed(Button.A)) {
basic.showString("hello world!")
} else {
basic.showString("PRESS A")
}
})
```
So, to recap: the `forever` block makes sure our code runs forever. The BBC micro:bit checks if the user is pressing the left button, if the user is not then the “Press the button!” message will scroll across the LEDs. If the user is pressing the button then the “hello, world!” message will scroll across the screen. Check this in the simulator or attach the BBC micro:bit to the computer then click **Download** to send the code onto the BBC micro:bit.

View File

@ -1,88 +0,0 @@
# blocks - challenges
Extra stuff for the Block Editor - an introduction to GPIO
## Before we get started
This section details challenges for the BBC micro:bit. Ensure you have completed all other sections of the Microsoft Block Editor tutorials before attempting these challenges!
## Quiz Challenge [1]
Using if statements, try to add more statements to create a simple quiz. The user will be told if the question is right or not, and will have two options (button A and button B).
Here is some sample code for a simple quiz:
![](/static/mb/blocks/lessons-0.png)
## Timer Challenge [2]
Create a timer that runs out after a certain amount of time (using the *count* loop). For an extra challenge, let the user input the amount of seconds they want the timer to run for using variables and the buttons as input. The solution is below.
![](/static/mb/blocks/lessons-1.png)
## Graphics Challenges [3]
Using the knowledge you have learnt from the [rendering graphics](/lessons/graphics) section, try creating an algorithm to draw these shapes. Before you write the code try to figure out how the BBC micro:bit will be thinking to plot these points. For example, with our diagonal line “count up from 0 to 4 by 1, and plot points x=i and y=i”.
* Another diagonal line
* A square going around the board
* A filled square
* A square which unplots itself after
* A filled square which then unplots itself
The solutions are below.
### Square [3.1]
![](/static/mb/blocks/lessons-2.png)
### Filled square [3.2]
![](/static/mb/blocks/lessons-3.png)
### Vanishing square [3.3]
Use the same code and algorithm for the square solution, only use the unplot block to make this LED turn off again. You could also reverse the algorithm.
### Vanishing filled square [3.4]
Use the same code and algorithm for the filled square solution, only use the `unplot` block to make this LED turn off again. You could also reverse the algorithm.
## Animation Challenge [4]
Use your new knowledge of animations and algorithms to program your BBC micro:bit to act human: for example, you could make your BBC micro:bit smile and wink. Remember you can display images with the `show image` and `create image` blocks. Sample code is below.
![](/static/mb/blocks/lessons-4.png)
## Electronic Dice Challenge [5]
Using the code in the Random Numbers tutorial in Section 6, or your own algorithm, create an electronic dice that displays the values appropriate for a dice (so 1 shows a single LED on in the center, two shows two LEDs on at each corner, etc.). You may want to declare image variables to do this, then check what it is equal to using an if statement. Sample code is below.
![](/static/mb/blocks/lessons-4.png)
## Calculator Challenge [6]
Using your knowledge of loops, counters and math, create a calculator.
The calculator should:
* Count the amount of times the user presses the left button before pressing the right button (this is the first value, or valueOne)
* Count the amount of times the user presses the left button before the right button again (this is the second value, or valueTwo)
* Scroll through operations (+,-, x and divide) until the user presses the right button to make a choice
* Perform the calculation
* Show the entire calculation, for example: 5 + 10 = 15
Sample code is below.
![](/static/mb/blocks/lessons-5.png)
## Smart watch Challenge [8]
Create a smart watch using the BBC micro:bit. Create a menu where the user presses one button to cycle through options and another button to choose this option. Add applications to this smart watch:
* Calculators
* Games
* Random number generators
And any other applications you can think of.

View File

@ -6,7 +6,9 @@ An introduction to graphics for the Block Editor.
Ensure you have completed the 'Hello, world!' and Loop tutorials and tested them on a simulator or on BBC micro:bit.
![](/static/mb/blocks/lessons/blocks-conditions-0.png)
```blocks
basic.showString("HI!");
```
The BBC micro:bit has a grid of 25 LEDs, so we can use these to display images.
@ -24,9 +26,16 @@ We can also code our bug to plot a point by giving an x (horizontal) and y (vert
We can also unplot a point (turn the LED off again) using the `unplot` block. So we could create a flashing LED program, using the `pause` block to create a delay.
![](/static/mb/blocks/lessons/graphics-1.png)
```blocks
basic.forever(() => {
led.plot(2,2)
basic.pause(100)
led.unplot(2,2)
basic.pause(100)
})
```
We can also use the `clear screen` block to turn off all LEDs.
We can also use the `basic.clearScreen` block to turn off all LEDs.
## Tip
@ -34,26 +43,35 @@ The pause block is in milliseconds, so setting it to 1000 will have a pause of a
### Devising algorithms for shapes
An algorithm is a set of steps to follow to solve a problem. We can begin to draw shapes on the BBC micro:bit using an algorithm. For example, we could draw a straight line with this code:
An algorithm is a set of steps to follow to solve a problem. We can begin to draw shapes on the BBC micro:bit using an algorithm.
For example, we could draw a straight line with this code:
![](/static/mb/blocks/lessons/graphics-2.png)
```blocks
for(let i = 0; i <=4; i++) {
led.plot(i, 0);
basic.pause(200)
}
```
Our algorithm is: increase **i** by 1 **from 0** to **4**, and **plot** the point **x=i**, **y=0**. The pause block allows this line to be animated (drawn frame by frame).
Try devising an algorithm for a diagonal line using the code above and the variable **i**. Your code should look like this; as our variable increases, so does the location that the BBC micro:bit is plotting at:
![](/static/mb/blocks/lessons/graphics-3.png)
We can create more complex algorithms for more complex shapes, too. See the [challenges](/lessons/challenges) section for additional graphical challenges and solutions.
Try devising an algorithm for a diagonal line using the code above and the variable **i**.
```sim
basic.forever(() => {
for(let i = 0; i <=4; i++) {
led.plot(i, i);
basic.pause(200)
}
basic.clearScreen();
})
```
### Animations
Animations are changes happening at a certain rate. For example, we could add the `delay` block from the **Basic** drawer with our square algorithm this will slowly draw a square (as an animation).
Animations are changes happening at a certain rate. For example, we could add the `pause` block from the **Basic** drawer with our square algorithm this will slowly draw a square (as an animation).
We could create more complex animations, for example we could make our BBC micro:bit display an explosion or fireworks.
See the [challenges](/lessons/challenges) section for some animation tasks.
### Image variables
We can create image variables so we can easily display an image at a later point. For example:

View File

@ -1,59 +0,0 @@
# blocks - loops
An introduction to Loops for the Block Editor.
We may want to handle the users input multiple times or remain waiting for their input for a long time. We use loops to make sure that our code runs multiple times. These can be found in the **Loops** drawer.
### Forever loops
In the Variables tutorial we utilised a forever loop to create a counter:
![](/static/mb/blocks/lessons/blocks-conditions-2.png)
This allows our BBC micro:bit to wait for the user to do something forever, for example wait for the user to press the correct button as the example above shows. If you were creating a quiz, you may want to loop forever until the user presses the correct button or answers the question.
### Repeat Loops
Repeat loops allow code to happen a certain amount of times. You may want to create a quiz that only gives the user a few tries to get the correct answer, for example. The number can be changed to facilitate your code.
![](/static/mb/blocks/lessons/loops-0.png)
The code above will scroll the message, “Hello world” three times.
### While & Until loops
The repeat while loop allows you to continue looping some code until a condition is met. The empty socket next to the while loop allows you to connect some Logic and construct a statement.
![](/static/mb/blocks/lessons/loops-1.png)
The code above will scroll the message, “Press it!”, while the user hasnt pressed the button.
* Drag a `set item` block from the **Variables** drawer. Click the **down arrow** and click **New Variable**, and type "pressed". Drag a `0` block from **Maths** to set the variable **pressed** to 0.
* Drag a `repeat while` block from the **Loops** drawer and attach an `=` block from the **Logic** drawer. Drag `item` from the **Variables** drawer and click the **down arrow**, select pressed. Drag a `0` block from Maths and connect it to the other side of the equals. This will carry out the code until pressed does not equal 0.
* Add a `show string` block from the **Basic** drawer and change the message to "Press it!"
* Add an `if` block from the **Logic** drawer, connect a `button pressed` block from the **Input** drawer, and add text from the **Basic** drawer. Change this to A to show we are waiting for button A.
* Inside the do part of the if statement, add a `set` block from the Variables drawer, click the **down arrow** to change it to **pressed** and drag a `1` from the Maths drawer
* Lastly underneath the while loop, add another `show string` block and fill in the gaps.
Test the code above on actual hardware or on the simulator window.
We can also change the code in subtle ways to have a completely different effect:
![](/static/mb/blocks/lessons/loops-2.png)
This time we have to press the button three times to leave the while loop.
## Tip
You can press the arrow next to a word in a block to change it. For example, you can change Math functions or change a Logic statement.
### Count or for loops
A count loop allows you to loop a certain amount of times and to change a variable as you do so. For example, we can create a simple counting program:
![](/static/mb/blocks/lessons/loops-3.png)
The count loop will repeat a certain amount of times whilst changing a variable. You can click the arrow next to **i** to replace it with any of your own variables. So this program will display numbers 1 to 10.
This loop allows you to repeat code for the amount of times you want to without worrying about manually changing variables. You could use this for a counting program or a timer.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 KiB

BIN
docs/static/mb/device/usb-osx-chrome.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/static/mb/device/usb-osx-device.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
docs/static/mb/device/usb-osx-dnd.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

View File

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 164 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

View File

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -101,38 +101,18 @@ namespace bluetooth {
uart = new MicroBitUARTService(*uBit.ble, 61, 60);
}
/**
* Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.
*/
//% help=bluetooth/uart-write
//% blockId=bluetooth_uart_write block="bluetooth uart write %data" blockGap=8
//% parts="bluetooth"
//%
void uartWrite(StringData *data) {
startUartService();
uart->send(ManagedString(data));
}
/**
* Reads from the Bluetooth UART service buffer, returning its contents when the specified delimiter character is encountered.
*/
//% help=bluetooth/uart-read
//% blockId=bluetooth_uart_read block="bluetooth uart read %del=bluetooth_uart_delimiter_conv" blockGap=8
//% parts="bluetooth"
//%
StringData* uartRead(StringData *del) {
startUartService();
return uart->readUntil(ManagedString(del)).leakData();
}
/**
* Returns the delimiter corresponding string
*/
//% blockId="bluetooth_uart_delimiter_conv" block="%del"
//% weight=1
//% parts="bluetooth"
StringData* delimiters(Delimiters del) {
ManagedString c("\n\n,$:.#"[max(0, min(6, (int)del))]);
return c.leakData();
}
/**
* Register code to run when the micro:bit is connected to over Bluetooth
* @param body Code to run when a Bluetooth connection is established

View File

@ -0,0 +1,43 @@
namespace bluetooth {
/**
* Returns the delimiter corresponding string
*/
//% blockId="bluetooth_uart_delimiter_conv" block="%del"
//% weight=1 parts="bluetooth"
export function delimiters(del: Delimiters): string {
// even though it might not look like, this is more
// (memory) efficient than the C++ implementation, because the
// strings are statically allocated and take no RAM
switch (del) {
case Delimiters.NewLine: return "\n"
case Delimiters.Comma: return ","
case Delimiters.Dollar: return "$"
case Delimiters.Colon: return ":"
case Delimiters.Fullstop: return "."
case Delimiters.Hash: return "#"
default: return "\n"
}
}
/**
* Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.
*/
//% help=bluetooth/uart-write
//% blockId=bluetooth_uart_write block="bluetooth uart write %data" blockGap=8
//% parts="bluetooth" shim=bluetooth::uartWrite
export function uartWrite(data: string): void {
// dummy implementation for simulator
console.log("UART Write: " + data)
}
/**
* Reads from the Bluetooth UART service buffer, returning its contents when the specified delimiter character is encountered.
*/
//% help=bluetooth/uart-read
//% blockId=bluetooth_uart_read block="bluetooth uart read %del=bluetooth_uart_delimiter_conv" blockGap=8
//% parts="bluetooth" shim=bluetooth::uartRead
export function uartRead(del: string): string {
// dummy implementation for simulator
return "???"
}
}

View File

@ -5,6 +5,7 @@
"README.md",
"enums.d.ts",
"shims.d.ts",
"bluetooth.ts",
"bluetooth.cpp"
],
"public": true,

View File

@ -63,30 +63,6 @@ declare namespace bluetooth {
//% parts="bluetooth" shim=bluetooth::startUartService
function startUartService(): void;
/**
* Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device.
*/
//% help=bluetooth/uart-write
//% blockId=bluetooth_uart_write block="bluetooth uart write %data" blockGap=8
//% parts="bluetooth" shim=bluetooth::uartWrite
function uartWrite(data: string): void;
/**
* Reads from the Bluetooth UART service buffer, returning its contents when the specified delimiter character is encountered.
*/
//% help=bluetooth/uart-read
//% blockId=bluetooth_uart_read block="bluetooth uart read %del=bluetooth_uart_delimiter_conv" blockGap=8
//% parts="bluetooth" shim=bluetooth::uartRead
function uartRead(del: string): string;
/**
* Returns the delimiter corresponding string
*/
//% blockId="bluetooth_uart_delimiter_conv" block="%del"
//% weight=1
//% parts="bluetooth" shim=bluetooth::delimiters
function delimiters(del: Delimiters): string;
/**
* Register code to run when the micro:bit is connected to over Bluetooth
* @param body Code to run when a Bluetooth connection is established

View File

@ -37,4 +37,11 @@ namespace control {
panic(98)
}
}
/**
* Display warning in the simulator.
*/
//% shim=pxtrt::runtimeWarning
export function runtimeWarning(message: string) {
}
}

View File

@ -316,4 +316,9 @@ namespace pxtrt {
void* getGlobalsPtr() {
return globals;
}
//%
void runtimeWarning(StringData *s) {
// noop for now
}
}

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -27,6 +27,8 @@
"serial.cpp",
"serial.ts",
"buffer.cpp",
"pxtparts.json",
"parts/speaker.svg",
"_locales/fr/microbit-jsdoc-strings.json"
],
"public": true,

View File

@ -0,0 +1,78 @@
{
"ledmatrix": {
"visual": "ledmatrix",
"breadboardColumnsNeeded": 8,
"breadboardStartRow": "h",
"pinAllocation": {
"type": "auto",
"gpioPinsNeeded": [5, 5]
},
"assemblyStep": 0,
"wires": [
{"start": ["breadboard", "j", 0], "end": ["GPIO", 5], "color": "purple", "assemblyStep": 1},
{"start": ["breadboard", "j", 1], "end": ["GPIO", 6], "color": "purple", "assemblyStep": 1},
{"start": ["breadboard", "j", 2], "end": ["GPIO", 7], "color": "purple", "assemblyStep": 1},
{"start": ["breadboard", "j", 3], "end": ["GPIO", 8], "color": "purple", "assemblyStep": 1},
{"start": ["breadboard", "a", 7], "end": ["GPIO", 9], "color": "purple", "assemblyStep": 1},
{"start": ["breadboard", "a", 0], "end": ["GPIO", 0], "color": "green", "assemblyStep": 2},
{"start": ["breadboard", "a", 1], "end": ["GPIO", 1], "color": "green", "assemblyStep": 2},
{"start": ["breadboard", "a", 2], "end": ["GPIO", 2], "color": "green", "assemblyStep": 2},
{"start": ["breadboard", "a", 3], "end": ["GPIO", 3], "color": "green", "assemblyStep": 2},
{"start": ["breadboard", "j", 4], "end": ["GPIO", 4], "color": "green", "assemblyStep": 2}
]
},
"buttonpair": {
"visual": "buttonpair",
"breadboardColumnsNeeded": 6,
"breadboardStartRow": "f",
"pinAllocation": {
"type": "predefined",
"pins": ["P13", "P12"]
},
"assemblyStep": 0,
"wires": [
{"start": ["breadboard", "j", 0], "end": ["GPIO", 0], "color": "yellow", "assemblyStep": 1},
{"start": ["breadboard", "a", 2], "end": "ground", "color": "blue", "assemblyStep": 1},
{"start": ["breadboard", "j", 3], "end": ["GPIO", 1], "color": "orange", "assemblyStep": 2},
{"start": ["breadboard", "a", 5], "end": "ground", "color": "blue", "assemblyStep": 2}
]
},
"neopixel": {
"visual": "neopixel",
"breadboardColumnsNeeded": 5,
"breadboardStartRow": "h",
"pinAllocation": {
"type": "factoryfunction",
"functionName": "neopixel.create",
"pinArgPositions": [0],
"otherArgPositions": [1]
},
"assemblyStep": 0,
"wires": [
{"start": ["breadboard", "j", 1], "end": "ground", "color": "blue", "assemblyStep": 1},
{"start": ["breadboard", "j", 2], "end": "threeVolt", "color": "red", "assemblyStep": 2},
{"start": ["breadboard", "j", 3], "end": ["GPIO", 0], "color": "green", "assemblyStep": 2}
]
},
"speaker": {
"visual": {
"image": "/parts/speaker.svg",
"width": 500,
"height": 500,
"firstPin": [180, 135],
"pinDist": 70,
"extraColumnOffset": 1
},
"breadboardColumnsNeeded": 5,
"breadboardStartRow": "f",
"pinAllocation": {
"type": "auto",
"gpioPinsNeeded": 1
},
"assemblyStep": 0,
"wires": [
{"start": ["breadboard", "j", 1], "end": ["GPIO", 0], "color": "#ff80fa", "assemblyStep": 1},
{"start": ["breadboard", "j", 3], "end": "ground", "color": "blue", "assemblyStep": 1}
]
}
}

View File

@ -1,141 +0,0 @@
# From Block Editor to Touch Develop
#docs
The Block Editor and Touch Develop programming languages provide similar features, but are not identical in their functionality. This presents a learning opportunity for teachers and students: to understand a few basic concepts and how they are expressed in different programming languages. The objective is to make students better able to navigate the sea of programming languages they will encounter later.
## Concept 1: Inclusive and exclusive intervals
In mathematics, numeric intervals are a useful shorthand for expressing a sequence of numbers. For example, the notation [0,9] represents the sequence of ten numbers 0,1,2,3,4,5,6,7,8,9. This is known as an "inclusive" interval because the sequence includes the endpoints of the interval, namely 0 and 9. On the other hand, the interval (0,9) represents the sequence of eight numbers 1,2,3,4,5,6,7,8 and is known as "exclusive".
In the interval notation, the brackets "[" and "]" represent inclusive endpoints and the parentheses "(" and ")" represent exclusive endpoints. Brackets can be mixed and matched, so [0,9) represents the sequence of nine numbers 0,1,2,3,4,5,6,7,8 while (0,9] represents the sequence of nine numbers 1,2,3,4,5,6,7,8,9. Let's call the former interval "inclusive-exclusive" and the latter interval "exclusive-inclusive".
### Block Editor for loop uses a 0-based inclusive interval
Numeric intervals arise in the context of for loops, both in the Block Editor and Touch Develop. Here's a Block Editor for loop to draw a diagonal line from the top-left corner of the [LED screen](/device/screen) to the bottom-right corner. The loop iteration variable *i* ranges "from 0 to 4":
![](/static/mb/blocks/to-td-0.png)
What interval does "from 0 to 4" represent? The answer is the inclusive interval [0,4], meaning that the loop iteration variable `i` will take on the values 0,1,2,3,4 over the *five* iterations of the loop. Experiments have shown that the *inclusive internal* is most familiar to students with no previous programming experience.
### TouchDevelop for loop uses a 0-based inclusive-exclusive interval
To achieve the same result in Touch Develop, we write the for loop slightly differently because the upper bound of the 0-based loop is *exclusive* rather than inclusive:
```
for (let i = 0; i < 5; i++) {
led.plot(i, i)
}
```
If we translated the Block Editor loop directly into Touch Develop, we would have:
```
for (let i1 = 0; i1 < 4; i1++) {
led.plot(i1, i1)
}
```
which would result in the loop iteration variable taking on values in the interval [0,4), namely 0,1,2,3.
### ~hint
The use of an exclusive upper-bound in for loops is standard practice in most programming languages. The basic reason for this is that with a 0-based inclusive lower bound, an exclusive upper bound U conveniently happens to be the length of the sequence represented by [0,U). This, of course, begs the question of why we count by starting with zero (0) in programming whereas we learn to count with one (1) in math.
### ~
## Concept 2: variable scope
A variable's *scope* is defined by two other concepts: its *lifetime* and *visibility*. Imagine program execution like a timeline with each point in the timeline being a step in the program's execution.
* A variable's *lifetime* can be thought of as an interval [birth, death) in the program execution during which the variable exists and has a value. Within that interval of the program execution, we say the variable is *alive*.
* A variable is visible if its value can be read/written at a point in program execution. Visibility often is based on program structure and where the current point of program execution is. Imagine program structure like a house with only doors and no windows: if you are outside the house, you cannot see the objects (variables) inside the house - they are not visible to you even though they may exist; however, if you enter the house through the door, you can see the variables inside the house. The house itself may be divided into rooms, each of which defines another space in which certain variables are visible and others are not visible.
A variable is "in scope" at a program point if it is both alive and visible at that point. A variable is "not in scope" if it is not alive or if it is not visible.
### The Block Editor has variables with only global scope
In the Block Editor, all variables are *global* variables, which means that all variables are alive and visible during the entire program execution. Consider the following Block Editor program:
![](/static/mb/blocks/to-td-1.png)
This program will draw a diagonal line, wait for one second and then show the value of global variable `i`. What number will be shown on the LED screen? After the fifth iteration of the for loop, the value of variable `i` is 4. At the end of this iteration, the variable `i` is incremented and takes on the value 5. Since 5 is greater than the upper (inclusive) endpoint of 4, the loop terminates with the value of `i` at 5.
### Problems with global variables: unintended interference
The Block Editor program belows shows a problem with having only variables with global scope. The intent of the program below is fairly clear: if the user presses button A, slowly draw a diagonal line from top-left to lower-right; if the user presses button B, slowly draw a diagonal line from top-right to lower-left. Pressing both buttons should lead to an X being displayed on the screen.
![](/static/mb/blocks/to-td-2.png)
The problem with the above program is that we have two loops using the same global variable *i* as the loop iteration variable. If the user first presses button A and then quickly presses button B, the loops execute concurrently, both reading and writing global variable *i* - this can cause unexpected results (in particular, you won't necessarily end up with an X displayed on the screen). You can see this more clearly by pressing the convert button in the Block Editor and examining the Touch Develop code that implements the Block Editor semantics:
![](/static/mb/blocks/to-td-3.png)
### JavaScript has variables with both local and global scope
In Touch Develop, in contrast to the Block Editor, the for-loop iteration variable has scope that is local to the loop:
```
for (let i2 = 0; i2 < 5; i2++) {
led.plot(i2, i2)
}
```
This means that:
1. the loop iteration variable *i* comes into existence just before the loop begins and goes out of existence just after the loop terminates.
2. the variable `i` only is visible from the code that appears textually between the `do` and `end` keywords of the for loop (this is known as lexical scoping).
The value of the loop iteration variable is completely determined by the semantics of the for loop. As such, Touch Develop doesn't allow the programmer to overwrite the value of a loop iteration variable, as shown below:
```
for (let i3 = 0; i3 < 5; i3++) {
led.plot(i3, i3)
i3 = 42
}
```
### Why is local scope useful?
Local scope allows you to use the same variable name in different parts of a program without concern about interference (as with variables with global scope). Here's the Touch Develop program that implements the "X" program without interference:
```
input.onButtonPressed(Button.A, () => {
for (let i4 = 0; i4 < 5; i4++) {
led.plot(i4, i4)
basic.pause(1000)
}
})
input.onButtonPressed(Button.B, () => {
for (let i5 = 0; i5 < 5; i5++) {
led.plot(4 - i5, i5)
basic.pause(1000)
}
})
```
Even though the same variable name (i) appears in both loops, these are different variables, each with their own lifetime and visibility (as defined by the for-loop).
## Concept 3: static types
A variable has a *static type* if it holds the same kind of value (integer, string, Boolean) everywhere that it is in scope. If a variable can hold values of different types at different program locations, then it does not have a static type.
### Block Editor blocks not plugged to an event will run
Blocks not plugged to an event will run. Blocks are running even if they are not inside of an `event`. As shown below, ``show string`` *Hello* will show a string on the LED screen one character at a time (scrolling from left to right).
![](/static/mb/blocks/to-td-4.png)
### Google's Blockly variables do not have static types
In Blockly, a variable can hold different types of values at different program locations. As shown below, the global variable *Count* can be first set to a number and later to a string:
![](/static/mb/blocks/to-td-5.png)
### Block Editor and Touch Develop variables have static types
In the Block Editor (based on Blockly) and Touch Develop, each variable has a static type. This means that some programs don't make sense, such as:
![](/static/mb/blocks/to-td-6.png)

View File

@ -1,6 +1,6 @@
{
"name": "pxt-microbit",
"version": "0.3.64",
"version": "0.3.78",
"description": "micro:bit target for PXT",
"keywords": [
"JavaScript",
@ -29,6 +29,6 @@
"typescript": "^1.8.7"
},
"dependencies": {
"pxt-core": "0.3.74"
"pxt-core": "0.3.92"
}
}

View File

@ -55,6 +55,63 @@ namespace pxsim {
gpioNeeded: number,
gpioAssigned: string[]
}
interface PowerUsage {
topGround: boolean,
topThreeVolt: boolean,
bottomGround: boolean,
bottomThreeVolt: boolean,
singleGround: boolean,
singleThreeVolt: boolean,
}
function isOnBreadboardBottom(location: WireLocationDefinition) {
let isBot = false;
if (location[0] === "breadboard") {
let row = <string>location[1];
isBot = 0 <= ["a", "b", "c", "d", "e"].indexOf(row);
}
return isBot;
}
const arrCount = (a: boolean[]) => a.reduce((p, n) => p + (n ? 1 : 0), 0);
const arrAny = (a: boolean[]) => arrCount(a) > 0;
function computePowerUsage(wireDef: WireDefinition): PowerUsage {
let ends = [wireDef.start, wireDef.end];
let endIsGround = ends.map(e => e === "ground");
let endIsThreeVolt = ends.map(e => e === "threeVolt");
let endIsBot = ends.map(e => isOnBreadboardBottom(e));
let hasGround = arrAny(endIsGround);
let hasThreeVolt = arrAny(endIsThreeVolt);
let hasBot = arrAny(endIsBot);
return {
topGround: hasGround && !hasBot,
topThreeVolt: hasThreeVolt && !hasBot,
bottomGround: hasGround && hasBot,
bottomThreeVolt: hasThreeVolt && hasBot,
singleGround: hasGround,
singleThreeVolt: hasThreeVolt
};
}
function mergePowerUsage(powerUsages: PowerUsage[]) {
let finalPowerUsage = powerUsages.reduce((p, n) => ({
topGround: p.topGround || n.topGround,
topThreeVolt: p.topThreeVolt || n.topThreeVolt,
bottomGround: p.bottomGround || n.bottomGround,
bottomThreeVolt: p.bottomThreeVolt || n.bottomThreeVolt,
singleGround: n.singleGround ? p.singleGround === null : p.singleGround,
singleThreeVolt: n.singleThreeVolt ? p.singleThreeVolt === null : p.singleThreeVolt,
}), {
topGround: false,
topThreeVolt: false,
bottomGround: false,
bottomThreeVolt: false,
singleGround: null,
singleThreeVolt: null,
});
if (finalPowerUsage.singleGround)
finalPowerUsage.topGround = finalPowerUsage.bottomGround = false;
if (finalPowerUsage.singleThreeVolt)
finalPowerUsage.topThreeVolt = finalPowerUsage.bottomThreeVolt = false;
return finalPowerUsage;
}
function copyDoubleArray(a: string[][]) {
return a.map(b => b.map(p => p));
}
@ -90,6 +147,7 @@ namespace pxsim {
ground: mkRange(1, 26).map(n => <BBRowCol>["-", `${n}`]),
},
};
private powerUsage: PowerUsage;
constructor(opts: AllocatorOpts) {
this.opts = opts;
@ -97,9 +155,17 @@ namespace pxsim {
private allocateLocation(location: WireLocationDefinition, opts: AllocLocOpts): Loc {
if (location === "ground" || location === "threeVolt") {
//special case if there is only a single ground or three volt pin in the whole build
if (location === "ground" && this.powerUsage.singleGround) {
let boardGroundPin = this.getBoardGroundPin();
return {type: "dalboard", pin: boardGroundPin};
} else if (location === "threeVolt" && this.powerUsage.singleThreeVolt) {
let boardThreeVoltPin = this.getBoardThreeVoltPin();
return {type: "dalboard", pin: boardThreeVoltPin};
}
U.assert(!!opts.nearestBBPin);
let nearLoc = opts.nearestBBPin;
let nearestCoord = this.opts.getBBCoord(nearLoc);
let nearestCoord = this.opts.getBBCoord(opts.nearestBBPin);
let firstTopAndBot = [
this.availablePowerPins.top.ground[0] || this.availablePowerPins.top.threeVolt[0],
this.availablePowerPins.bottom.ground[0] || this.availablePowerPins.bottom.threeVolt[0]
@ -111,31 +177,31 @@ namespace pxsim {
//TODO
}
let nearTop = visuals.findClosestCoordIdx(nearestCoord, firstTopAndBot) == 0;
let pins: BBRowCol[];
let barPins: BBRowCol[];
if (nearTop) {
if (location === "ground") {
pins = this.availablePowerPins.top.ground;
barPins = this.availablePowerPins.top.ground;
} else if (location === "threeVolt") {
pins = this.availablePowerPins.top.threeVolt;
barPins = this.availablePowerPins.top.threeVolt;
}
} else {
if (location === "ground") {
pins = this.availablePowerPins.bottom.ground;
barPins = this.availablePowerPins.bottom.ground;
} else if (location === "threeVolt") {
pins = this.availablePowerPins.bottom.threeVolt;
barPins = this.availablePowerPins.bottom.threeVolt;
}
}
let pinCoords = pins.map(rowCol => {
let pinCoords = barPins.map(rowCol => {
return this.opts.getBBCoord(rowCol);
});
let pinIdx = visuals.findClosestCoordIdx(nearestCoord, pinCoords);
let pin = pins[pinIdx];
let closestPinIdx = visuals.findClosestCoordIdx(nearestCoord, pinCoords);
let pin = barPins[closestPinIdx];
if (nearTop) {
this.availablePowerPins.top.ground.splice(pinIdx, 1);
this.availablePowerPins.top.threeVolt.splice(pinIdx, 1);
this.availablePowerPins.top.ground.splice(closestPinIdx, 1);
this.availablePowerPins.top.threeVolt.splice(closestPinIdx, 1);
} else {
this.availablePowerPins.bottom.ground.splice(pinIdx, 1);
this.availablePowerPins.bottom.threeVolt.splice(pinIdx, 1);
this.availablePowerPins.bottom.ground.splice(closestPinIdx, 1);
this.availablePowerPins.bottom.threeVolt.splice(closestPinIdx, 1);
}
return {type: "breadboard", rowCol: pin};
} else if (location[0] === "breadboard") {
@ -148,23 +214,41 @@ namespace pxsim {
let idx = <number>location[1];
let pin = opts.cmpGPIOPins[idx];
return {type: "dalboard", pin: pin};
} else if (location === "MOSI" || location === "MISO" || location === "SCK") {
if (!this.opts.boardDef.spiPins)
console.debug("No SPI pin mappings found!");
let pin = (<any>this.opts.boardDef.spiPins)[location as string] as string;
return {type: "dalboard", pin: pin};
} else if (location === "SDA" || location === "SCL") {
if (!this.opts.boardDef.i2cPins)
console.debug("No I2C pin mappings found!");
let pin = (<any>this.opts.boardDef.i2cPins)[location as string] as string;
return {type: "dalboard", pin: pin};
} else {
//TODO
U.assert(false);
return null;
}
}
private allocatePowerWires(): WireInst[] {
private getBoardGroundPin() {
let boardGround = this.opts.boardDef.groundPins[0] || null;
if (!boardGround) {
console.log("No available ground pin on board!");
//TODO
}
return boardGround;
}
private getBoardThreeVoltPin() {
let threeVoltPin = this.opts.boardDef.threeVoltPins[0] || null;
if (!threeVoltPin) {
console.log("No available 3.3V pin on board!");
//TODO
}
return threeVoltPin;
}
private allocatePowerWires(powerUsage: PowerUsage): WireInst[] {
let boardGroundPin = this.getBoardGroundPin();
let threeVoltPin = this.getBoardThreeVoltPin();
let topLeft: BBRowCol = ["-", "26"];
let botLeft: BBRowCol = ["-", "1"];
let topRight: BBRowCol = ["-", "50"];
@ -179,34 +263,71 @@ namespace pxsim {
}
const GROUND_COLOR = "blue";
const POWER_COLOR = "red";
const wires: WireInst[] = [
{start: this.allocateLocation("ground", {nearestBBPin: top}),
end: this.allocateLocation("ground", {nearestBBPin: bot}),
color: GROUND_COLOR, assemblyStep: 0},
{start: this.allocateLocation("ground", {nearestBBPin: top}),
end: {type: "dalboard", pin: boardGround},
color: GROUND_COLOR, assemblyStep: 0},
{start: this.allocateLocation("threeVolt", {nearestBBPin: top}),
end: this.allocateLocation("threeVolt", {nearestBBPin: bot}),
color: POWER_COLOR, assemblyStep: 1},
{start: this.allocateLocation("threeVolt", {nearestBBPin: top}),
end: {type: "dalboard", pin: threeVoltPin},
color: POWER_COLOR, assemblyStep: 1},
];
const wires: WireInst[] = [];
let groundStep = 0;
let threeVoltStep = (powerUsage.bottomGround || powerUsage.topGround) ? 1 : 0;
if (powerUsage.bottomGround && powerUsage.topGround) {
//bb top - <==> bb bot -
wires.push({
start: this.allocateLocation("ground", {nearestBBPin: top}),
end: this.allocateLocation("ground", {nearestBBPin: bot}),
color: GROUND_COLOR, assemblyStep: groundStep
});
}
if (powerUsage.topGround) {
//board - <==> bb top -
wires.push({
start: this.allocateLocation("ground", {nearestBBPin: top}),
end: {type: "dalboard", pin: boardGroundPin},
color: GROUND_COLOR, assemblyStep: groundStep
});
} else if (powerUsage.bottomGround) {
//board - <==> bb bot -
wires.push({
start: this.allocateLocation("ground", {nearestBBPin: bot}),
end: {type: "dalboard", pin: boardGroundPin},
color: GROUND_COLOR, assemblyStep: groundStep
});
}
if (powerUsage.bottomThreeVolt && powerUsage.bottomGround) {
//bb top + <==> bb bot +
wires.push({
start: this.allocateLocation("threeVolt", {nearestBBPin: top}),
end: this.allocateLocation("threeVolt", {nearestBBPin: bot}),
color: POWER_COLOR, assemblyStep: threeVoltStep
});
}
if (powerUsage.topThreeVolt) {
//board + <==> bb top +
wires.push({
start: this.allocateLocation("threeVolt", {nearestBBPin: top}),
end: {type: "dalboard", pin: threeVoltPin},
color: POWER_COLOR, assemblyStep: threeVoltStep
});
} else if (powerUsage.bottomThreeVolt) {
//board + <==> bb bot +
wires.push({
start: this.allocateLocation("threeVolt", {nearestBBPin: bot}),
end: {type: "dalboard", pin: threeVoltPin},
color: POWER_COLOR, assemblyStep: threeVoltStep
});
}
return wires;
}
private allocateWire(wireDef: WireDefinition, opts: AllocWireOpts): WireInst {
let ends = [wireDef.start, wireDef.end];
let endIsPower = ends.map(e => e === "ground" || e === "threeVolt");
//allocate non-power first so we know the nearest pin for the power end
let endInsts = ends.map((e, idx) => !endIsPower[idx] ? this.allocateLocation(e, opts) : null)
//allocate power pins closest to the other end of the wire
endInsts = endInsts.map((e, idx) => {
if (e)
return e;
let locInst = <BBLoc>endInsts[1 - idx];
let locInst = <BBLoc>endInsts[1 - idx]; // non-power end
let l = this.allocateLocation(ends[idx], {
nearestBBPin: locInst.rowCol,
startColumn: opts.startColumn,
cmpGPIOPins: opts.cmpGPIOPins
cmpGPIOPins: opts.cmpGPIOPins,
});
return l;
});
@ -404,8 +525,11 @@ namespace pxsim {
let basicWires: WireInst[] = [];
let cmpsAndWires: CmpAndWireInst[] = [];
if (cmpList.length > 0) {
basicWires = this.allocatePowerWires();
let partialCmps = this.allocatePartialCmps();
let allWireDefs = partialCmps.map(p => p.def.wires).reduce((p, n) => p.concat(n), []);
let allPowerUsage = allWireDefs.map(w => computePowerUsage(w));
this.powerUsage = mergePowerUsage(allPowerUsage);
basicWires = this.allocatePowerWires(this.powerUsage);
let cmpGPIOPins = this.allocateGPIOPins(partialCmps);
let reverseMap = mkReverseMap(this.opts.boardDef.gpioPinMap);
let cmpMicrobitPins = cmpGPIOPins.map(pins => pins.map(p => reverseMap[p]));

View File

@ -1,3 +1,5 @@
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
namespace pxsim {
export class DalBoard extends BaseBoard {
id: string;
@ -69,12 +71,14 @@ namespace pxsim {
}
initAsync(msg: SimulatorRunMessage): Promise<void> {
super.initAsync(msg);
let options = (msg.options || {}) as RuntimeOptions;
let boardDef = CURRENT_BOARD; //TODO: read from pxt.json/pxttarget.json
let cmpsList = msg.parts;
let cmpDefs = PART_DEFINITIONS; //TODO: read from pxt.json/pxttarget.json
let cmpDefs = msg.partDefinitions || {}; //TODO: read from pxt.json/pxttarget.json
let fnArgs = msg.fnArgs;
let viewHost = new visuals.BoardHost({

Some files were not shown because too many files have changed in this diff Show More