Compare commits
34 Commits
Author | SHA1 | Date | |
---|---|---|---|
90f7b229d1 | |||
c54e0b0e9d | |||
ea088ac828 | |||
29cf4d3e53 | |||
6d637eefd7 | |||
6310e96ac2 | |||
dbb1e31822 | |||
5376bc2dce | |||
57bd293df8 | |||
e570d46755 | |||
d37f284fce | |||
b716226889 | |||
1bd19cc1a0 | |||
ac8c9c5e85 | |||
057260c483 | |||
568ae32f81 | |||
ae605ff829 | |||
f25ddb1085 | |||
f175f973f0 | |||
c7e5fa490e | |||
61a29f7c67 | |||
50293fc654 | |||
a9ecadaf09 | |||
6e56107eb5 | |||
1f077beb65 | |||
8fff762156 | |||
cebded2526 | |||
13f53d730a | |||
8adcab1cab | |||
8cb5f442f9 | |||
96448d5237 | |||
30f01bb0ac | |||
3d0b397de2 | |||
e0de55d689 |
@ -53,11 +53,6 @@ pxt update
|
|||||||
|
|
||||||
More instructions at https://github.com/Microsoft/pxt#running-a-target-from-localhost
|
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
|
### Building
|
||||||
|
|
||||||
* Install Visual Studio 2015 Update 2 or higher. Make sure the Windows 10 templates are installed.
|
* Install Visual Studio 2015 Update 2 or higher. Make sure the Windows 10 templates are installed.
|
||||||
|
@ -28,7 +28,7 @@ export function deployCoreAsync(res: ts.pxtc.CompileResult) {
|
|||||||
|
|
||||||
function getBitDrivesAsync(): Promise<string[]> {
|
function getBitDrivesAsync(): Promise<string[]> {
|
||||||
if (process.platform == "win32") {
|
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")
|
return execAsync("wmic PATH Win32_LogicalDisk get DeviceID, VolumeName, FileSystem")
|
||||||
.then(buf => {
|
.then(buf => {
|
||||||
let res: string[] = []
|
let res: string[] = []
|
||||||
@ -42,9 +42,14 @@ function getBitDrivesAsync(): Promise<string[]> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
else if (process.platform == "darwin") {
|
else if (process.platform == "darwin") {
|
||||||
let rx = new RegExp(pxt.appTarget.compile.deployDrives)
|
const rx = new RegExp(pxt.appTarget.compile.deployDrives)
|
||||||
return readDirAsync("/Volumes")
|
return readDirAsync("/Volumes")
|
||||||
.then(lst => lst.filter(s => rx.test(s)).map(s => "/Volumes/" + s + "/"))
|
.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 {
|
} else {
|
||||||
return Promise.resolve([])
|
return Promise.resolve([])
|
||||||
}
|
}
|
||||||
|
@ -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
|
While you're writing and testing your programs, you'll mostly be [running them
|
||||||
(see [run code in your browser](/device/simulator) for info about this).
|
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
|
## Requirements
|
||||||
|
|
||||||
You need the following things to transfer and run a script on your micro:bit:
|
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-Male to Micro USB cable to connect your computer to your micro:bit. This is
|
||||||
* a PC running Windows 7 of later, or a Mac running OS X 10.6 or later
|
the same cable that is commonly used to connect a smart phone to a computer.
|
||||||
* access to the Internet
|
* 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
|
## 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.
|
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**
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Mac (picture bvabdbco)
|
**Mac**
|
||||||
WARN: unknown picture: bvabdbco:5x3
|
|
||||||
|
|
||||||
## Step 2: Compile your script
|

|
||||||
|
|
||||||
Next, compile your script:
|
## Step 2: Download your program
|
||||||
|
|
||||||
1. Sign in to Touch Develop on your computer.
|
1. Open your project on [codethemicrobit.com](https://codethemicrobit.com)
|
||||||
|
2. Click **Download**
|
||||||
2. Open your script (find the script in **My Scripts** and click `Edit`).
|
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
|
||||||
3. Click **Download**. Your script is converted into a hex file that you can transfer and run on your micro:bit.
|
whether you are using a Windows computer or a Mac
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
### Windows
|
### 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.
|

|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||

|
#### 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.
|

|
||||||
|
|
||||||

|
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.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**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**:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Then click **Open folder** and drag and drop the file from your Downloads to
|
||||||
|
your `MICROBIT` drive.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### Internet Explorer
|
||||||
|
|
||||||
|
A message will appear at the bottom of the browser asking what you want to do
|
||||||
|
with the file. Click **Save**:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Then click **Open folder** and drag and drop the file from your Downloads to
|
||||||
|
your `MICROBIT` drive.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
### Mac
|
### 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:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**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.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**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.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Step 3: Transfer the file to your micro:bit
|
## Step 3: Transfer the file to your micro:bit
|
||||||
|
|
||||||
1. The file will transfer onto your micro:bit.
|
* Once you've found the folder containing your `.hex` file, drag and drop it
|
||||||
|
onto your `MICROBIT` drive
|
||||||
2. If you're using Windows, you can use **Send to** as described below.
|
* 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
|
||||||
3. The LED on the back of your micro:bit flashes during the transfer (which should only take a few seconds).
|
should only take a few seconds).
|
||||||
|
* Once transferred, the code will run automatically on your micro:bit. To rerun
|
||||||
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.
|
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:
|
**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**.
|
- In File Explorer, right-click on the hex file (created in Step 2 above), choose **Send to**, and then **MICROBIT**.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
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
|
## Troubleshooting
|
||||||
|
|
||||||
You can’t 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 can’t 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:
|
The errors may look like this:
|
||||||
|
|
||||||
**Windows**
|
**Windows**
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**Mac**
|
**Mac**
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Or it may appear that there are two hex files on your micro:bit so the micro:bit won’t 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
|
||||||
|
won’t 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
|
### See also
|
||||||
|
|
||||||
|
BIN
docs/static/mb/device/pins-0.png
vendored
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 77 KiB |
BIN
docs/static/mb/device/usb-1.jpg
vendored
Before Width: | Height: | Size: 391 KiB |
BIN
docs/static/mb/device/usb-10.png
vendored
Before Width: | Height: | Size: 25 KiB |
BIN
docs/static/mb/device/usb-2.jpg
vendored
Before Width: | Height: | Size: 289 KiB |
BIN
docs/static/mb/device/usb-3.jpg
vendored
Before Width: | Height: | Size: 385 KiB |
BIN
docs/static/mb/device/usb-4.jpg
vendored
Before Width: | Height: | Size: 180 KiB |
BIN
docs/static/mb/device/usb-5.jpg
vendored
Before Width: | Height: | Size: 121 KiB |
BIN
docs/static/mb/device/usb-6.jpg
vendored
Before Width: | Height: | Size: 336 KiB |
BIN
docs/static/mb/device/usb-7.jpg
vendored
Before Width: | Height: | Size: 324 KiB |
BIN
docs/static/mb/device/usb-osx-chrome.png
vendored
Normal file
After Width: | Height: | Size: 186 KiB |
BIN
docs/static/mb/device/usb-osx-copy-file-error.png
vendored
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
docs/static/mb/device/usb-osx-device.png
vendored
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
docs/static/mb/device/usb-osx-dnd.png
vendored
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
docs/static/mb/device/usb-osx-firefox-1.png
vendored
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
docs/static/mb/device/usb-osx-firefox-2.png
vendored
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
docs/static/mb/device/usb-windows-chrome.png
vendored
Normal file
After Width: | Height: | Size: 162 KiB |
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 164 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
BIN
docs/static/mb/device/usb-windows-edge-1.png
vendored
Normal file
After Width: | Height: | Size: 156 KiB |
BIN
docs/static/mb/device/usb-windows-edge-2.png
vendored
Normal file
After Width: | Height: | Size: 135 KiB |
BIN
docs/static/mb/device/usb-windows-firefox-1.png
vendored
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
docs/static/mb/device/usb-windows-firefox-2.png
vendored
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
docs/static/mb/device/usb-windows-ie11-1.png
vendored
Normal file
After Width: | Height: | Size: 164 KiB |
BIN
docs/static/mb/device/usb-windows-ie11-2.png
vendored
Normal file
After Width: | Height: | Size: 159 KiB |
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 160 KiB |
BIN
docs/static/mb/js/basicFuns.png
vendored
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 15 KiB |
BIN
docs/static/mb/js/basicIntell.png
vendored
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 22 KiB |
BIN
docs/static/mb/js/forIntell.png
vendored
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 7.9 KiB |
@ -37,4 +37,11 @@ namespace control {
|
|||||||
panic(98)
|
panic(98)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display warning in the simulator.
|
||||||
|
*/
|
||||||
|
//% shim=pxtrt::runtimeWarning
|
||||||
|
export function runtimeWarning(message: string) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,4 +316,9 @@ namespace pxtrt {
|
|||||||
void* getGlobalsPtr() {
|
void* getGlobalsPtr() {
|
||||||
return globals;
|
return globals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//%
|
||||||
|
void runtimeWarning(StringData *s) {
|
||||||
|
// noop for now
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pxt-microbit",
|
"name": "pxt-microbit",
|
||||||
"version": "0.3.73",
|
"version": "0.3.77",
|
||||||
"description": "micro:bit target for PXT",
|
"description": "micro:bit target for PXT",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"JavaScript",
|
"JavaScript",
|
||||||
@ -29,6 +29,6 @@
|
|||||||
"typescript": "^1.8.7"
|
"typescript": "^1.8.7"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pxt-core": "0.3.84"
|
"pxt-core": "0.3.90"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
176
sim/allocator.ts
@ -55,6 +55,63 @@ namespace pxsim {
|
|||||||
gpioNeeded: number,
|
gpioNeeded: number,
|
||||||
gpioAssigned: string[]
|
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[][]) {
|
function copyDoubleArray(a: string[][]) {
|
||||||
return a.map(b => b.map(p => p));
|
return a.map(b => b.map(p => p));
|
||||||
}
|
}
|
||||||
@ -90,6 +147,7 @@ namespace pxsim {
|
|||||||
ground: mkRange(1, 26).map(n => <BBRowCol>["-", `${n}`]),
|
ground: mkRange(1, 26).map(n => <BBRowCol>["-", `${n}`]),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
private powerUsage: PowerUsage;
|
||||||
|
|
||||||
constructor(opts: AllocatorOpts) {
|
constructor(opts: AllocatorOpts) {
|
||||||
this.opts = opts;
|
this.opts = opts;
|
||||||
@ -97,9 +155,17 @@ namespace pxsim {
|
|||||||
|
|
||||||
private allocateLocation(location: WireLocationDefinition, opts: AllocLocOpts): Loc {
|
private allocateLocation(location: WireLocationDefinition, opts: AllocLocOpts): Loc {
|
||||||
if (location === "ground" || location === "threeVolt") {
|
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);
|
U.assert(!!opts.nearestBBPin);
|
||||||
let nearLoc = opts.nearestBBPin;
|
let nearestCoord = this.opts.getBBCoord(opts.nearestBBPin);
|
||||||
let nearestCoord = this.opts.getBBCoord(nearLoc);
|
|
||||||
let firstTopAndBot = [
|
let firstTopAndBot = [
|
||||||
this.availablePowerPins.top.ground[0] || this.availablePowerPins.top.threeVolt[0],
|
this.availablePowerPins.top.ground[0] || this.availablePowerPins.top.threeVolt[0],
|
||||||
this.availablePowerPins.bottom.ground[0] || this.availablePowerPins.bottom.threeVolt[0]
|
this.availablePowerPins.bottom.ground[0] || this.availablePowerPins.bottom.threeVolt[0]
|
||||||
@ -111,31 +177,31 @@ namespace pxsim {
|
|||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
let nearTop = visuals.findClosestCoordIdx(nearestCoord, firstTopAndBot) == 0;
|
let nearTop = visuals.findClosestCoordIdx(nearestCoord, firstTopAndBot) == 0;
|
||||||
let pins: BBRowCol[];
|
let barPins: BBRowCol[];
|
||||||
if (nearTop) {
|
if (nearTop) {
|
||||||
if (location === "ground") {
|
if (location === "ground") {
|
||||||
pins = this.availablePowerPins.top.ground;
|
barPins = this.availablePowerPins.top.ground;
|
||||||
} else if (location === "threeVolt") {
|
} else if (location === "threeVolt") {
|
||||||
pins = this.availablePowerPins.top.threeVolt;
|
barPins = this.availablePowerPins.top.threeVolt;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (location === "ground") {
|
if (location === "ground") {
|
||||||
pins = this.availablePowerPins.bottom.ground;
|
barPins = this.availablePowerPins.bottom.ground;
|
||||||
} else if (location === "threeVolt") {
|
} 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);
|
return this.opts.getBBCoord(rowCol);
|
||||||
});
|
});
|
||||||
let pinIdx = visuals.findClosestCoordIdx(nearestCoord, pinCoords);
|
let closestPinIdx = visuals.findClosestCoordIdx(nearestCoord, pinCoords);
|
||||||
let pin = pins[pinIdx];
|
let pin = barPins[closestPinIdx];
|
||||||
if (nearTop) {
|
if (nearTop) {
|
||||||
this.availablePowerPins.top.ground.splice(pinIdx, 1);
|
this.availablePowerPins.top.ground.splice(closestPinIdx, 1);
|
||||||
this.availablePowerPins.top.threeVolt.splice(pinIdx, 1);
|
this.availablePowerPins.top.threeVolt.splice(closestPinIdx, 1);
|
||||||
} else {
|
} else {
|
||||||
this.availablePowerPins.bottom.ground.splice(pinIdx, 1);
|
this.availablePowerPins.bottom.ground.splice(closestPinIdx, 1);
|
||||||
this.availablePowerPins.bottom.threeVolt.splice(pinIdx, 1);
|
this.availablePowerPins.bottom.threeVolt.splice(closestPinIdx, 1);
|
||||||
}
|
}
|
||||||
return {type: "breadboard", rowCol: pin};
|
return {type: "breadboard", rowCol: pin};
|
||||||
} else if (location[0] === "breadboard") {
|
} else if (location[0] === "breadboard") {
|
||||||
@ -164,17 +230,25 @@ namespace pxsim {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private allocatePowerWires(): WireInst[] {
|
private getBoardGroundPin() {
|
||||||
let boardGround = this.opts.boardDef.groundPins[0] || null;
|
let boardGround = this.opts.boardDef.groundPins[0] || null;
|
||||||
if (!boardGround) {
|
if (!boardGround) {
|
||||||
console.log("No available ground pin on board!");
|
console.log("No available ground pin on board!");
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
return boardGround;
|
||||||
|
}
|
||||||
|
private getBoardThreeVoltPin() {
|
||||||
let threeVoltPin = this.opts.boardDef.threeVoltPins[0] || null;
|
let threeVoltPin = this.opts.boardDef.threeVoltPins[0] || null;
|
||||||
if (!threeVoltPin) {
|
if (!threeVoltPin) {
|
||||||
console.log("No available 3.3V pin on board!");
|
console.log("No available 3.3V pin on board!");
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
return threeVoltPin;
|
||||||
|
}
|
||||||
|
private allocatePowerWires(powerUsage: PowerUsage): WireInst[] {
|
||||||
|
let boardGroundPin = this.getBoardGroundPin();
|
||||||
|
let threeVoltPin = this.getBoardThreeVoltPin();
|
||||||
let topLeft: BBRowCol = ["-", "26"];
|
let topLeft: BBRowCol = ["-", "26"];
|
||||||
let botLeft: BBRowCol = ["-", "1"];
|
let botLeft: BBRowCol = ["-", "1"];
|
||||||
let topRight: BBRowCol = ["-", "50"];
|
let topRight: BBRowCol = ["-", "50"];
|
||||||
@ -189,30 +263,67 @@ namespace pxsim {
|
|||||||
}
|
}
|
||||||
const GROUND_COLOR = "blue";
|
const GROUND_COLOR = "blue";
|
||||||
const POWER_COLOR = "red";
|
const POWER_COLOR = "red";
|
||||||
const wires: WireInst[] = [
|
const wires: WireInst[] = [];
|
||||||
{start: this.allocateLocation("ground", {nearestBBPin: top}),
|
let groundStep = 0;
|
||||||
end: this.allocateLocation("ground", {nearestBBPin: bot}),
|
let threeVoltStep = (powerUsage.bottomGround || powerUsage.topGround) ? 1 : 0;
|
||||||
color: GROUND_COLOR, assemblyStep: 0},
|
if (powerUsage.bottomGround && powerUsage.topGround) {
|
||||||
{start: this.allocateLocation("ground", {nearestBBPin: top}),
|
//bb top - <==> bb bot -
|
||||||
end: {type: "dalboard", pin: boardGround},
|
wires.push({
|
||||||
color: GROUND_COLOR, assemblyStep: 0},
|
start: this.allocateLocation("ground", {nearestBBPin: top}),
|
||||||
{start: this.allocateLocation("threeVolt", {nearestBBPin: top}),
|
end: this.allocateLocation("ground", {nearestBBPin: bot}),
|
||||||
end: this.allocateLocation("threeVolt", {nearestBBPin: bot}),
|
color: GROUND_COLOR, assemblyStep: groundStep
|
||||||
color: POWER_COLOR, assemblyStep: 1},
|
});
|
||||||
{start: this.allocateLocation("threeVolt", {nearestBBPin: top}),
|
}
|
||||||
end: {type: "dalboard", pin: threeVoltPin},
|
if (powerUsage.topGround) {
|
||||||
color: POWER_COLOR, assemblyStep: 1},
|
//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;
|
return wires;
|
||||||
}
|
}
|
||||||
private allocateWire(wireDef: WireDefinition, opts: AllocWireOpts): WireInst {
|
private allocateWire(wireDef: WireDefinition, opts: AllocWireOpts): WireInst {
|
||||||
let ends = [wireDef.start, wireDef.end];
|
let ends = [wireDef.start, wireDef.end];
|
||||||
let endIsPower = ends.map(e => e === "ground" || e === "threeVolt");
|
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)
|
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) => {
|
endInsts = endInsts.map((e, idx) => {
|
||||||
if (e)
|
if (e)
|
||||||
return e;
|
return e;
|
||||||
let locInst = <BBLoc>endInsts[1 - idx];
|
let locInst = <BBLoc>endInsts[1 - idx]; // non-power end
|
||||||
let l = this.allocateLocation(ends[idx], {
|
let l = this.allocateLocation(ends[idx], {
|
||||||
nearestBBPin: locInst.rowCol,
|
nearestBBPin: locInst.rowCol,
|
||||||
startColumn: opts.startColumn,
|
startColumn: opts.startColumn,
|
||||||
@ -414,8 +525,11 @@ namespace pxsim {
|
|||||||
let basicWires: WireInst[] = [];
|
let basicWires: WireInst[] = [];
|
||||||
let cmpsAndWires: CmpAndWireInst[] = [];
|
let cmpsAndWires: CmpAndWireInst[] = [];
|
||||||
if (cmpList.length > 0) {
|
if (cmpList.length > 0) {
|
||||||
basicWires = this.allocatePowerWires();
|
|
||||||
let partialCmps = this.allocatePartialCmps();
|
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 cmpGPIOPins = this.allocateGPIOPins(partialCmps);
|
||||||
let reverseMap = mkReverseMap(this.opts.boardDef.gpioPinMap);
|
let reverseMap = mkReverseMap(this.opts.boardDef.gpioPinMap);
|
||||||
let cmpMicrobitPins = cmpGPIOPins.map(pins => pins.map(p => reverseMap[p]));
|
let cmpMicrobitPins = cmpGPIOPins.map(pins => pins.map(p => reverseMap[p]));
|
||||||
|
@ -131,7 +131,8 @@ namespace pxsim.instructions {
|
|||||||
wireClr?: string,
|
wireClr?: string,
|
||||||
cmpWidth?: number,
|
cmpWidth?: number,
|
||||||
cmpHeight?: number,
|
cmpHeight?: number,
|
||||||
cmpScale?: number
|
cmpScale?: number,
|
||||||
|
crocClips?: boolean
|
||||||
};
|
};
|
||||||
function mkBoardImgSvg(def: string | BoardImageDefinition): visuals.SVGElAndSize {
|
function mkBoardImgSvg(def: string | BoardImageDefinition): visuals.SVGElAndSize {
|
||||||
let boardView: visuals.BoardView;
|
let boardView: visuals.BoardView;
|
||||||
@ -154,7 +155,7 @@ namespace pxsim.instructions {
|
|||||||
//TODO: Refactor this function; it is too complicated. There is a lot of error-prone math being done
|
//TODO: Refactor this function; it is too complicated. There is a lot of error-prone math being done
|
||||||
// to scale and place all elements which could be simplified with more forethought.
|
// to scale and place all elements which could be simplified with more forethought.
|
||||||
let svgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
let svgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||||
let dims = {l: 0, t: 0, w: 0, h: 0};
|
let dims = { l: 0, t: 0, w: 0, h: 0 };
|
||||||
|
|
||||||
let cmpSvgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
let cmpSvgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||||
svgEl.appendChild(cmpSvgEl);
|
svgEl.appendChild(cmpSvgEl);
|
||||||
@ -181,7 +182,7 @@ namespace pxsim.instructions {
|
|||||||
scale(opts.cmpHeight / dims.h)
|
scale(opts.cmpHeight / dims.h)
|
||||||
}
|
}
|
||||||
svg.hydrate(cmpSvgEl, cmpSvgAtts);
|
svg.hydrate(cmpSvgEl, cmpSvgAtts);
|
||||||
let elDims = {l: dims.l, t: dims.t, w: dims.w, h: dims.h};
|
let elDims = { l: dims.l, t: dims.t, w: dims.w, h: dims.h };
|
||||||
|
|
||||||
let updateL = (newL: number) => {
|
let updateL = (newL: number) => {
|
||||||
if (newL < dims.l) {
|
if (newL < dims.l) {
|
||||||
@ -287,13 +288,13 @@ namespace pxsim.instructions {
|
|||||||
let el: visuals.SVGElAndSize;
|
let el: visuals.SVGElAndSize;
|
||||||
if (cmp == "wire") {
|
if (cmp == "wire") {
|
||||||
//TODO: support non-croc wire parts
|
//TODO: support non-croc wire parts
|
||||||
el = visuals.mkWirePart([0, 0], opts.wireClr || "red", true);
|
el = visuals.mkWirePart([0, 0], opts.wireClr || "red", opts.crocClips);
|
||||||
} else if (typeof cmp == "string") {
|
} else if (typeof cmp == "string") {
|
||||||
let builtinVis = <string>cmp;
|
let builtinVis = <string>cmp;
|
||||||
let cnstr = builtinComponentPartVisual[builtinVis];
|
let cnstr = builtinComponentPartVisual[builtinVis];
|
||||||
el = cnstr([0, 0]);
|
el = cnstr([0, 0]);
|
||||||
} else {
|
} else {
|
||||||
let partVis = <PartVisualDefinition> cmp;
|
let partVis = <PartVisualDefinition>cmp;
|
||||||
el = visuals.mkGenericPartSVG(partVis);
|
el = visuals.mkGenericPartSVG(partVis);
|
||||||
}
|
}
|
||||||
return wrapSvg(el, opts);
|
return wrapSvg(el, opts);
|
||||||
@ -320,8 +321,8 @@ namespace pxsim.instructions {
|
|||||||
let step = w.assemblyStep + 1;
|
let step = w.assemblyStep + 1;
|
||||||
(stepToWires[step] || (stepToWires[step] = [])).push(w)
|
(stepToWires[step] || (stepToWires[step] = [])).push(w)
|
||||||
});
|
});
|
||||||
let getMaxStep = (ns: {assemblyStep: number}[]) => ns.reduce((m, n) => Math.max(m, n.assemblyStep), 0);
|
let getMaxStep = (ns: { assemblyStep: number }[]) => ns.reduce((m, n) => Math.max(m, n.assemblyStep), 0);
|
||||||
let stepOffset = getMaxStep(powerWires) + 2;
|
let stepOffset = powerWires.length > 0 ? getMaxStep(powerWires) + 2 : 1;
|
||||||
components.forEach(cAndWs => {
|
components.forEach(cAndWs => {
|
||||||
let {component, wires} = cAndWs;
|
let {component, wires} = cAndWs;
|
||||||
let cStep = component.assemblyStep + stepOffset;
|
let cStep = component.assemblyStep + stepOffset;
|
||||||
@ -451,10 +452,10 @@ namespace pxsim.instructions {
|
|||||||
|
|
||||||
// board and breadboard
|
// board and breadboard
|
||||||
let boardImg = mkBoardImgSvg(props.boardDef.visual);
|
let boardImg = mkBoardImgSvg(props.boardDef.visual);
|
||||||
let board = wrapSvg(boardImg, {left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BOARD_SCALE});
|
let board = wrapSvg(boardImg, { left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BOARD_SCALE });
|
||||||
panel.appendChild(board);
|
panel.appendChild(board);
|
||||||
let bbRaw = mkBBSvg();
|
let bbRaw = mkBBSvg();
|
||||||
let bb = wrapSvg(bbRaw, {left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BB_SCALE});
|
let bb = wrapSvg(bbRaw, { left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BB_SCALE });
|
||||||
panel.appendChild(bb);
|
panel.appendChild(bb);
|
||||||
|
|
||||||
// components
|
// components
|
||||||
@ -481,7 +482,8 @@ namespace pxsim.instructions {
|
|||||||
left: QUANT_LBL(quant),
|
left: QUANT_LBL(quant),
|
||||||
leftSize: WIRE_QUANT_LBL_SIZE,
|
leftSize: WIRE_QUANT_LBL_SIZE,
|
||||||
wireClr: clr,
|
wireClr: clr,
|
||||||
cmpScale: PARTS_WIRE_SCALE
|
cmpScale: PARTS_WIRE_SCALE,
|
||||||
|
crocClips: props.boardDef.useCrocClips
|
||||||
})
|
})
|
||||||
addClass(cmp, "partslist-wire");
|
addClass(cmp, "partslist-wire");
|
||||||
panel.appendChild(cmp);
|
panel.appendChild(cmp);
|
||||||
@ -526,7 +528,8 @@ namespace pxsim.instructions {
|
|||||||
bot: mkLabel(w.start),
|
bot: mkLabel(w.start),
|
||||||
botSize: LOC_LBL_SIZE,
|
botSize: LOC_LBL_SIZE,
|
||||||
wireClr: w.color,
|
wireClr: w.color,
|
||||||
cmpHeight: REQ_WIRE_HEIGHT
|
cmpHeight: REQ_WIRE_HEIGHT,
|
||||||
|
crocClips: props.boardDef.useCrocClips
|
||||||
})
|
})
|
||||||
addClass(cmp, "cmp-div");
|
addClass(cmp, "cmp-div");
|
||||||
reqsDiv.appendChild(cmp);
|
reqsDiv.appendChild(cmp);
|
||||||
@ -592,7 +595,7 @@ namespace pxsim.instructions {
|
|||||||
//we use the docs renderer to decompile the code to blocks and render it
|
//we use the docs renderer to decompile the code to blocks and render it
|
||||||
//TODO: render the blocks code directly
|
//TODO: render the blocks code directly
|
||||||
let md =
|
let md =
|
||||||
`\`\`\`blocks
|
`\`\`\`blocks
|
||||||
${tsCode}
|
${tsCode}
|
||||||
\`\`\`
|
\`\`\`
|
||||||
\`\`\`package
|
\`\`\`package
|
||||||
@ -600,9 +603,9 @@ ${tsPackage}
|
|||||||
\`\`\`
|
\`\`\`
|
||||||
`
|
`
|
||||||
|
|
||||||
pxtdocs.requireMarked = function() { return (<any>window).marked; }
|
pxtdocs.requireMarked = function () { return (<any>window).marked; }
|
||||||
pxtrunner.renderMarkdownAsync(codeContainerDiv, md)
|
pxtrunner.renderMarkdownAsync(codeContainerDiv, md)
|
||||||
.done(function() {
|
.done(function () {
|
||||||
let codeSvg = $("#proj-code-container svg");
|
let codeSvg = $("#proj-code-container svg");
|
||||||
if (codeSvg.length > 0) {
|
if (codeSvg.length > 0) {
|
||||||
//code rendered successfully as blocks
|
//code rendered successfully as blocks
|
||||||
|
@ -5,14 +5,33 @@
|
|||||||
namespace pxsim {
|
namespace pxsim {
|
||||||
export type BBRowCol = [/*row*/string, /*column*/string];
|
export type BBRowCol = [/*row*/string, /*column*/string];
|
||||||
export type BoardPin = string;
|
export type BoardPin = string;
|
||||||
export interface BBLoc {type: "breadboard", rowCol: BBRowCol};
|
export interface BBLoc { type: "breadboard", rowCol: BBRowCol };
|
||||||
export interface BoardLoc {type: "dalboard", pin: BoardPin};
|
export interface BoardLoc { type: "dalboard", pin: BoardPin };
|
||||||
export type Loc = BBLoc | BoardLoc;
|
export type Loc = BBLoc | BoardLoc;
|
||||||
|
|
||||||
export function initRuntimeWithDalBoard() {
|
export function initRuntimeWithDalBoard() {
|
||||||
U.assert(!runtime.board);
|
U.assert(!runtime.board);
|
||||||
let b = new DalBoard();
|
let b = new DalBoard();
|
||||||
runtime.board = b;
|
runtime.board = b;
|
||||||
|
runtime.postError = (e) => {
|
||||||
|
led.setBrightness(255);
|
||||||
|
let img = board().ledMatrixState.image;
|
||||||
|
img.clear();
|
||||||
|
img.set(0, 4, 255);
|
||||||
|
img.set(1, 3, 255);
|
||||||
|
img.set(2, 3, 255);
|
||||||
|
img.set(3, 3, 255);
|
||||||
|
img.set(4, 4, 255);
|
||||||
|
img.set(0, 0, 255);
|
||||||
|
img.set(1, 0, 255);
|
||||||
|
img.set(0, 1, 255);
|
||||||
|
img.set(1, 1, 255);
|
||||||
|
img.set(3, 0, 255);
|
||||||
|
img.set(4, 0, 255);
|
||||||
|
img.set(3, 1, 255);
|
||||||
|
img.set(4, 1, 255);
|
||||||
|
runtime.updateDisplay();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!pxsim.initCurrentRuntime) {
|
if (!pxsim.initCurrentRuntime) {
|
||||||
pxsim.initCurrentRuntime = initRuntimeWithDalBoard;
|
pxsim.initCurrentRuntime = initRuntimeWithDalBoard;
|
||||||
@ -31,7 +50,7 @@ namespace pxsim {
|
|||||||
|
|
||||||
export function parseQueryString(): (key: string) => string {
|
export function parseQueryString(): (key: string) => string {
|
||||||
let qs = window.location.search.substring(1);
|
let qs = window.location.search.substring(1);
|
||||||
let getQsVal = (key: string) => decodeURIComponent((qs.split(`${key}=`)[1] || "").split("&")[0] || "").replace(/\+/g, " ");
|
let getQsVal = (key: string) => decodeURIComponent((qs.split(`${key}=`)[1] || "").split("&")[0] || ""); //.replace(/\+/g, " ");
|
||||||
return getQsVal;
|
return getQsVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,15 +69,15 @@ namespace pxsim.visuals {
|
|||||||
move: "pointermove",
|
move: "pointermove",
|
||||||
leave: "pointerleave"
|
leave: "pointerleave"
|
||||||
} : {
|
} : {
|
||||||
up: "mouseup",
|
up: "mouseup",
|
||||||
down: "mousedown",
|
down: "mousedown",
|
||||||
move: "mousemove",
|
move: "mousemove",
|
||||||
leave: "mouseleave"
|
leave: "mouseleave"
|
||||||
};
|
};
|
||||||
|
|
||||||
export function translateEl(el: SVGElement, xy: [number, number]) {
|
export function translateEl(el: SVGElement, xy: [number, number]) {
|
||||||
//TODO append translation instead of replacing the full transform
|
//TODO append translation instead of replacing the full transform
|
||||||
svg.hydrate(el, {transform: `translate(${xy[0]} ${xy[1]})`});
|
svg.hydrate(el, { transform: `translate(${xy[0]} ${xy[1]})` });
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ComposeOpts {
|
export interface ComposeOpts {
|
||||||
@ -83,14 +102,14 @@ namespace pxsim.visuals {
|
|||||||
export function composeSVG(opts: ComposeOpts): ComposeResult {
|
export function composeSVG(opts: ComposeOpts): ComposeResult {
|
||||||
let [a, b] = [opts.el1, opts.el2];
|
let [a, b] = [opts.el1, opts.el2];
|
||||||
U.assert(a.x == 0 && a.y == 0 && b.x == 0 && b.y == 0, "el1 and el2 x,y offsets not supported");
|
U.assert(a.x == 0 && a.y == 0 && b.x == 0 && b.y == 0, "el1 and el2 x,y offsets not supported");
|
||||||
let setXY = (e: SVGSVGElement, x: number, y: number) => svg.hydrate(e, {x: x, y: y});
|
let setXY = (e: SVGSVGElement, x: number, y: number) => svg.hydrate(e, { x: x, y: y });
|
||||||
let setWH = (e: SVGSVGElement, w: string, h: string) => {
|
let setWH = (e: SVGSVGElement, w: string, h: string) => {
|
||||||
if (w)
|
if (w)
|
||||||
svg.hydrate(e, {width: w});
|
svg.hydrate(e, { width: w });
|
||||||
if (h)
|
if (h)
|
||||||
svg.hydrate(e, {height: h});
|
svg.hydrate(e, { height: h });
|
||||||
}
|
}
|
||||||
let setWHpx = (e: SVGSVGElement, w: number, h: number) => svg.hydrate(e, {width: `${w}px`, height: `${h}px`});
|
let setWHpx = (e: SVGSVGElement, w: number, h: number) => svg.hydrate(e, { width: `${w}px`, height: `${h}px` });
|
||||||
let scaleUnit = opts.scaleUnit2;
|
let scaleUnit = opts.scaleUnit2;
|
||||||
let aScalar = opts.scaleUnit2 / opts.scaleUnit1;
|
let aScalar = opts.scaleUnit2 / opts.scaleUnit1;
|
||||||
let bScalar = 1.0;
|
let bScalar = 1.0;
|
||||||
@ -157,11 +176,11 @@ namespace pxsim.visuals {
|
|||||||
let w = scaleFn(opts.width);
|
let w = scaleFn(opts.width);
|
||||||
let h = scaleFn(opts.height);
|
let h = scaleFn(opts.height);
|
||||||
let img = <SVGImageElement>svg.elt("image", {
|
let img = <SVGImageElement>svg.elt("image", {
|
||||||
width: w,
|
width: w,
|
||||||
height: h,
|
height: h,
|
||||||
"href": `${opts.image}`
|
"href": `${opts.image}`
|
||||||
});
|
});
|
||||||
return {el: img, w: w, h: h, x: 0, y: 0};
|
return { el: img, w: w, h: h, x: 0, y: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Coord = [number, number];
|
export type Coord = [number, number];
|
||||||
@ -190,13 +209,15 @@ namespace pxsim.visuals {
|
|||||||
|
|
||||||
export function mkTxt(cx: number, cy: number, size: number, rot: number, txt: string, txtXOffFactor?: number, txtYOffFactor?: number): SVGTextElement {
|
export function mkTxt(cx: number, cy: number, size: number, rot: number, txt: string, txtXOffFactor?: number, txtYOffFactor?: number): SVGTextElement {
|
||||||
let el = <SVGTextElement>svg.elt("text")
|
let el = <SVGTextElement>svg.elt("text")
|
||||||
//HACK: these constants (txtXOffFactor, txtYOffFactor) tweak the way this algorithm knows how to center the text
|
//HACK: these constants (txtXOffFactor, txtYOffFactor) tweak the way this algorithm knows how to center the text
|
||||||
txtXOffFactor = txtXOffFactor || -0.33333;
|
txtXOffFactor = txtXOffFactor || -0.33333;
|
||||||
txtYOffFactor = txtYOffFactor || 0.3;
|
txtYOffFactor = txtYOffFactor || 0.3;
|
||||||
const xOff = txtXOffFactor * size * txt.length;
|
const xOff = txtXOffFactor * size * txt.length;
|
||||||
const yOff = txtYOffFactor * size;
|
const yOff = txtYOffFactor * size;
|
||||||
svg.hydrate(el, {style: `font-size:${size}px;`,
|
svg.hydrate(el, {
|
||||||
transform: `translate(${cx} ${cy}) rotate(${rot}) translate(${xOff} ${yOff})` });
|
style: `font-size:${size}px;`,
|
||||||
|
transform: `translate(${cx} ${cy}) rotate(${rot}) translate(${xOff} ${yOff})`
|
||||||
|
});
|
||||||
svg.addClass(el, "noselect");
|
svg.addClass(el, "noselect");
|
||||||
el.textContent = txt;
|
el.textContent = txt;
|
||||||
return el;
|
return el;
|
||||||
|
@ -195,26 +195,24 @@ namespace pxsim.images {
|
|||||||
|
|
||||||
namespace pxsim.ImageMethods {
|
namespace pxsim.ImageMethods {
|
||||||
export function showImage(leds: Image, offset: number) {
|
export function showImage(leds: Image, offset: number) {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
|
|
||||||
leds.copyTo(offset, 5, board().ledMatrixState.image, 0)
|
leds.copyTo(offset, 5, board().ledMatrixState.image, 0)
|
||||||
runtime.queueDisplayUpdate()
|
runtime.queueDisplayUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function plotImage(leds: Image, offset: number): void {
|
export function plotImage(leds: Image, offset: number): void {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
|
|
||||||
leds.copyTo(offset, 5, board().ledMatrixState.image, 0)
|
leds.copyTo(offset, 5, board().ledMatrixState.image, 0)
|
||||||
runtime.queueDisplayUpdate()
|
runtime.queueDisplayUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function height(leds: Image): number {
|
export function height(leds: Image): number {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
return Image.height;
|
return Image.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function width(leds: Image): number {
|
export function width(leds: Image): number {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
return leds.width;
|
return leds.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,35 +225,32 @@ namespace pxsim.ImageMethods {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function pixel(leds: Image, x: number, y: number): number {
|
export function pixel(leds: Image, x: number, y: number): number {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
return leds.get(x, y);
|
return leds.get(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setPixel(leds: Image, x: number, y: number, v: number) {
|
export function setPixel(leds: Image, x: number, y: number, v: number) {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
leds.set(x, y, v);
|
leds.set(x, y, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clear(leds: Image) {
|
export function clear(leds: Image) {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
|
|
||||||
leds.clear();
|
leds.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setPixelBrightness(i: Image, x: number, y: number, b: number) {
|
export function setPixelBrightness(i: Image, x: number, y: number, b: number) {
|
||||||
if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(i)
|
||||||
|
|
||||||
i.set(x, y, b);
|
i.set(x, y, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pixelBrightness(i: Image, x: number, y: number): number {
|
export function pixelBrightness(i: Image, x: number, y: number): number {
|
||||||
if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(i)
|
||||||
|
|
||||||
return i.get(x, y);
|
return i.get(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function scrollImage(leds: Image, stride: number, interval: number): void {
|
export function scrollImage(leds: Image, stride: number, interval: number): void {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
if (stride == 0) stride = 1;
|
if (stride == 0) stride = 1;
|
||||||
|
|
||||||
let cb = getResume();
|
let cb = getResume();
|
||||||
|
@ -19,24 +19,6 @@ namespace pxsim {
|
|||||||
|
|
||||||
export function panic(code: number) {
|
export function panic(code: number) {
|
||||||
console.log("PANIC:", code)
|
console.log("PANIC:", code)
|
||||||
led.setBrightness(255);
|
|
||||||
let img = board().ledMatrixState.image;
|
|
||||||
img.clear();
|
|
||||||
img.set(0, 4, 255);
|
|
||||||
img.set(1, 3, 255);
|
|
||||||
img.set(2, 3, 255);
|
|
||||||
img.set(3, 3, 255);
|
|
||||||
img.set(4, 4, 255);
|
|
||||||
img.set(0, 0, 255);
|
|
||||||
img.set(1, 0, 255);
|
|
||||||
img.set(0, 1, 255);
|
|
||||||
img.set(1, 1, 255);
|
|
||||||
img.set(3, 0, 255);
|
|
||||||
img.set(4, 0, 255);
|
|
||||||
img.set(3, 1, 255);
|
|
||||||
img.set(4, 1, 255);
|
|
||||||
runtime.updateDisplay();
|
|
||||||
|
|
||||||
throw new Error("PANIC " + code)
|
throw new Error("PANIC " + code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|