Compare commits
107 Commits
Author | SHA1 | Date | |
---|---|---|---|
e31279938b | |||
2655843b74 | |||
527d323ea7 | |||
5d40a48477 | |||
850fb54f52 | |||
6bb35c1a72 | |||
6569231ba6 | |||
a3a1c8a480 | |||
c90dfaa6e7 | |||
02cd0e1da3 | |||
0f9dde0c4e | |||
1e0cd48316 | |||
d959282c68 | |||
d513ad7713 | |||
b7da28285e | |||
dbaf406703 | |||
2cb467f22b | |||
9585e2276d | |||
a591d9f072 | |||
471a30ca3d | |||
205b94afe8 | |||
18caf554e9 | |||
67cdf16fe4 | |||
bdbe8371dd | |||
21a36eb9ee | |||
376b20b035 | |||
7ce41b52aa | |||
46f7831e7c | |||
dda29a5cb6 | |||
6e4f4595a2 | |||
cdbe1e513b | |||
ae15c9a656 | |||
d993ff3a9d | |||
13785a2438 | |||
4dfb77fcd7 | |||
70deffb665 | |||
41a148de28 | |||
886e071d7f | |||
8a58d664c3 | |||
71d1155f21 | |||
167c1d8fce | |||
e59ae37954 | |||
72a621ec8b | |||
d6ff930333 | |||
54a7ac81ea | |||
e5d985dbf1 | |||
9db91d89d6 | |||
1fa9bf12d5 | |||
61bab257eb | |||
2e90b351da | |||
801bd6c7a0 | |||
777ba40899 | |||
0d11c16ecf | |||
9c1628b977 | |||
953b362b34 | |||
8b40850a94 | |||
fc3a02cc41 | |||
80f2ff6757 | |||
6f790d167c | |||
ac7502074a | |||
50473255a8 | |||
910772d54e | |||
33f12f9ecc | |||
01fa4ef53a | |||
3858b0a0a0 | |||
da30afb121 | |||
086bcf372f | |||
236e7337e2 | |||
4cf223271f | |||
10180f4729 | |||
618dd33221 | |||
7356e5e52e | |||
a59d148eb5 | |||
34ce687bbd | |||
5e241ed566 | |||
dcb2b21e66 | |||
95669e174a | |||
aca7d6113d | |||
ef4b06a087 | |||
afa69c23c4 | |||
8229e71d0a | |||
93770e5821 | |||
cb8e28beb0 | |||
8c7e6055ff | |||
8450db55ac | |||
c63e2c85f1 | |||
d8fc11a688 | |||
847a29848d | |||
39f4372ee5 | |||
a8bbbea8ed | |||
91a8d05e45 | |||
3ecedd3a32 | |||
b6390d77dd | |||
e8f9e0f023 | |||
2bacb58fdd | |||
af8babfea2 | |||
1ee6274100 | |||
7448db5b98 | |||
983645403b | |||
7a9f382bee | |||
e59fd8469b | |||
008c886de9 | |||
c87fa30738 | |||
dd9d1299fa | |||
6a7d1bd95c | |||
dfe270d259 | |||
6deb0683b6 |
2
clients/electron/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
projects
|
5
clients/electron/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# PXT micro:bit Electron app
|
||||||
|
|
||||||
|
A very basic wrapper around the web app. To install, copy the contents of this
|
||||||
|
directory to somewhere outside the main `pxt-microbit` repository. Then run `npm
|
||||||
|
install && npm start`.
|
15
clients/electron/index.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>code the micro:bit</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<webview id="webview" style="position:absolute; left:0; top:0; right:0; bottom:0"/>
|
||||||
|
<script>
|
||||||
|
const webview = document.getElementById("webview")
|
||||||
|
const url = `http://localhost:3232/${window.location.hash}`
|
||||||
|
webview.src = url
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,67 +1,39 @@
|
|||||||
const electron = require('electron')
|
const {app, BrowserWindow, Menu} = require('electron')
|
||||||
// Module to control application life.
|
|
||||||
const app = electron.app
|
|
||||||
// Module to create native browser window.
|
|
||||||
const BrowserWindow = electron.BrowserWindow
|
|
||||||
// pxt toolchain
|
|
||||||
const pxt = require('pxt-core')
|
const pxt = require('pxt-core')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
// Keep a global reference of the window object, if you don't, the window will
|
let win
|
||||||
// be closed automatically when the JavaScript object is garbage collected.
|
|
||||||
let mainWindow
|
|
||||||
|
|
||||||
function createWindow() {
|
const cliPath = path.join(process.cwd(), "node_modules/pxt-microbit")
|
||||||
console.log('starting app...')
|
|
||||||
// Create the browser window.
|
function startServerAndCreateWindow() {
|
||||||
mainWindow = new BrowserWindow({
|
pxt.mainCli(cliPath, ["serve", "-no-browser"])
|
||||||
width: 800, height: 600,
|
createWindow()
|
||||||
webPreferences: {
|
}
|
||||||
nodeIntegration: false,
|
|
||||||
}
|
function createWindow () {
|
||||||
|
win = new BrowserWindow({
|
||||||
|
width: 800,
|
||||||
|
height: 600,
|
||||||
|
title: "code the micro:bit"
|
||||||
})
|
})
|
||||||
|
Menu.setApplicationMenu(null)
|
||||||
ts.pxt.Util.debug = true;
|
win.loadURL(`file://${__dirname}/index.html#local_token=${pxt.globalConfig.localToken}`)
|
||||||
pxt.mainCli("C:/gh/pxt-microbit/clients/electron/node_modules/pxt-microbit", ["serve", "-just"]);
|
win.on('closed', () => {
|
||||||
|
win = null
|
||||||
// no menu
|
|
||||||
mainWindow.setMenu(null);
|
|
||||||
|
|
||||||
// and load the index.html of the app.
|
|
||||||
mainWindow.loadURL(`http://localhost:3232/#local_token=08ba9b8f-6ccb-4202-296d-28fac7a553d9`)
|
|
||||||
|
|
||||||
// Open the DevTools.
|
|
||||||
mainWindow.webContents.openDevTools()
|
|
||||||
|
|
||||||
// Emitted when the window is closed.
|
|
||||||
mainWindow.on('closed', function () {
|
|
||||||
// Dereference the window object, usually you would store windows
|
|
||||||
// in an array if your app supports multi windows, this is the time
|
|
||||||
// when you should delete the corresponding element.
|
|
||||||
mainWindow = null
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method will be called when Electron has finished
|
app.on('ready', startServerAndCreateWindow)
|
||||||
// initialization and is ready to create browser windows.
|
|
||||||
// Some APIs can only be used after this event occurs.
|
|
||||||
app.on('ready', createWindow)
|
|
||||||
|
|
||||||
// Quit when all windows are closed.
|
app.on('window-all-closed', () => {
|
||||||
app.on('window-all-closed', function () {
|
|
||||||
// On OS X it is common for applications and their menu bar
|
|
||||||
// to stay active until the user quits explicitly with Cmd + Q
|
|
||||||
if (process.platform !== 'darwin') {
|
if (process.platform !== 'darwin') {
|
||||||
app.quit()
|
app.quit()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
app.on('activate', function () {
|
app.on('activate', () => {
|
||||||
// On OS X it's common to re-create a window in the app when the
|
if (win === null) {
|
||||||
// dock icon is clicked and there are no other windows open.
|
|
||||||
if (mainWindow === null) {
|
|
||||||
createWindow()
|
createWindow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// In this file you can include the rest of your app's specific main process
|
|
||||||
// code. You can also put them in separate files and require them here.
|
|
@ -1,19 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "codethemicrobit",
|
"name" : "code-the-microbit",
|
||||||
"version": "0.1.0",
|
"version" : "1.0.0",
|
||||||
"description": "A Blocks / JavaScript editor for the micro:bit",
|
"description": "Blocks / Javascript editor",
|
||||||
"main": "main.js",
|
|
||||||
"scripts": {
|
|
||||||
"start": "electron ."
|
|
||||||
},
|
|
||||||
"author": "Microsoft",
|
"author": "Microsoft",
|
||||||
"license": "MIT",
|
"main" : "main.js",
|
||||||
"devDependencies": {
|
"scripts": {
|
||||||
"electron-prebuilt": "^1.2.0"
|
"start": "node_modules/.bin/electron ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"devDependencies": {
|
||||||
"typescript": "1.8.7",
|
"electron": "*",
|
||||||
"pxt-core": "*",
|
|
||||||
"pxt-microbit": "*"
|
"pxt-microbit": "*"
|
||||||
}
|
}
|
||||||
}
|
}
|
137
clients/macuploader/.gitignore
vendored
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
|
||||||
|
# Created by https://www.gitignore.io/api/osx,xcode,objective-c,vim
|
||||||
|
|
||||||
|
### OSX ###
|
||||||
|
*.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
|
||||||
|
### Xcode ###
|
||||||
|
# Xcode
|
||||||
|
#
|
||||||
|
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||||
|
|
||||||
|
## Build generated
|
||||||
|
build/
|
||||||
|
DerivedData/
|
||||||
|
|
||||||
|
## Various settings
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
xcuserdata/
|
||||||
|
|
||||||
|
## Other
|
||||||
|
*.moved-aside
|
||||||
|
*.xccheckout
|
||||||
|
*.xcscmblueprint
|
||||||
|
|
||||||
|
|
||||||
|
### Objective-C ###
|
||||||
|
# Xcode
|
||||||
|
#
|
||||||
|
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||||
|
|
||||||
|
## Build generated
|
||||||
|
build/
|
||||||
|
DerivedData/
|
||||||
|
|
||||||
|
## Various settings
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
xcuserdata/
|
||||||
|
|
||||||
|
## Other
|
||||||
|
*.moved-aside
|
||||||
|
*.xcuserstate
|
||||||
|
|
||||||
|
## Obj-C/Swift specific
|
||||||
|
*.hmap
|
||||||
|
*.ipa
|
||||||
|
*.dSYM.zip
|
||||||
|
*.dSYM
|
||||||
|
|
||||||
|
# CocoaPods
|
||||||
|
#
|
||||||
|
# We recommend against adding the Pods directory to your .gitignore. However
|
||||||
|
# you should judge for yourself, the pros and cons are mentioned at:
|
||||||
|
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||||
|
#
|
||||||
|
# Pods/
|
||||||
|
|
||||||
|
# Carthage
|
||||||
|
#
|
||||||
|
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||||
|
# Carthage/Checkouts
|
||||||
|
|
||||||
|
Carthage/Build
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
#
|
||||||
|
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||||
|
# screenshots whenever they are needed.
|
||||||
|
# For more information about the recommended setup visit:
|
||||||
|
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
|
||||||
|
|
||||||
|
fastlane/report.xml
|
||||||
|
fastlane/Preview.html
|
||||||
|
fastlane/screenshots
|
||||||
|
fastlane/test_output
|
||||||
|
|
||||||
|
# Code Injection
|
||||||
|
#
|
||||||
|
# After new code Injection tools there's a generated folder /iOSInjectionProject
|
||||||
|
# https://github.com/johnno1962/injectionforxcode
|
||||||
|
|
||||||
|
iOSInjectionProject/
|
||||||
|
|
||||||
|
### Objective-C Patch ###
|
||||||
|
*.xcscmblueprint
|
||||||
|
|
||||||
|
|
||||||
|
### Vim ###
|
||||||
|
# swap
|
||||||
|
[._]*.s[a-w][a-z]
|
||||||
|
[._]s[a-w][a-z]
|
||||||
|
# session
|
||||||
|
Session.vim
|
||||||
|
# temporary
|
||||||
|
.netrwhist
|
||||||
|
*~
|
||||||
|
# auto-generated tag files
|
||||||
|
tags
|
BIN
clients/macuploader/Graphics/appicon.sketch
Normal file
BIN
clients/macuploader/Graphics/export.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
clients/macuploader/Graphics/menubar.sketch
Normal file
307
clients/macuploader/Microbit Uploader.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 46;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
E93040071D895D1F00D931CA /* DirectoryWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = E93040061D895D1F00D931CA /* DirectoryWatcher.m */; };
|
||||||
|
E930400A1D89620900D931CA /* Uploader.m in Sources */ = {isa = PBXBuildFile; fileRef = E93040091D89620900D931CA /* Uploader.m */; };
|
||||||
|
E9F4FEE21D8709980071D783 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E9F4FEE11D8709980071D783 /* AppDelegate.m */; };
|
||||||
|
E9F4FEE51D8709980071D783 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E9F4FEE41D8709980071D783 /* main.m */; };
|
||||||
|
E9F4FEE71D8709980071D783 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E9F4FEE61D8709980071D783 /* Assets.xcassets */; };
|
||||||
|
E9F4FEEA1D8709980071D783 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = E9F4FEE81D8709980071D783 /* MainMenu.xib */; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
E93040051D895D1F00D931CA /* DirectoryWatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DirectoryWatcher.h; sourceTree = "<group>"; };
|
||||||
|
E93040061D895D1F00D931CA /* DirectoryWatcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DirectoryWatcher.m; sourceTree = "<group>"; };
|
||||||
|
E93040081D89620900D931CA /* Uploader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Uploader.h; sourceTree = "<group>"; };
|
||||||
|
E93040091D89620900D931CA /* Uploader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Uploader.m; sourceTree = "<group>"; };
|
||||||
|
E9F4FEDD1D8709980071D783 /* Microbit Uploader.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Microbit Uploader.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
E9F4FEE01D8709980071D783 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||||
|
E9F4FEE11D8709980071D783 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||||
|
E9F4FEE41D8709980071D783 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||||
|
E9F4FEE61D8709980071D783 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
E9F4FEE91D8709980071D783 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||||
|
E9F4FEEB1D8709980071D783 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
E9F4FEDA1D8709980071D783 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
E9F4FED41D8709980071D783 = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E9F4FEDF1D8709980071D783 /* Microbit Uploader */,
|
||||||
|
E9F4FEDE1D8709980071D783 /* Products */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
E9F4FEDE1D8709980071D783 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E9F4FEDD1D8709980071D783 /* Microbit Uploader.app */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
E9F4FEDF1D8709980071D783 /* Microbit Uploader */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E9F4FEE01D8709980071D783 /* AppDelegate.h */,
|
||||||
|
E9F4FEE11D8709980071D783 /* AppDelegate.m */,
|
||||||
|
E9F4FEE61D8709980071D783 /* Assets.xcassets */,
|
||||||
|
E9F4FEE81D8709980071D783 /* MainMenu.xib */,
|
||||||
|
E9F4FEEB1D8709980071D783 /* Info.plist */,
|
||||||
|
E9F4FEE31D8709980071D783 /* Supporting Files */,
|
||||||
|
E93040051D895D1F00D931CA /* DirectoryWatcher.h */,
|
||||||
|
E93040061D895D1F00D931CA /* DirectoryWatcher.m */,
|
||||||
|
E93040081D89620900D931CA /* Uploader.h */,
|
||||||
|
E93040091D89620900D931CA /* Uploader.m */,
|
||||||
|
);
|
||||||
|
path = "Microbit Uploader";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
E9F4FEE31D8709980071D783 /* Supporting Files */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E9F4FEE41D8709980071D783 /* main.m */,
|
||||||
|
);
|
||||||
|
name = "Supporting Files";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
E9F4FEDC1D8709980071D783 /* Microbit Uploader */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = E9F4FEEE1D8709980071D783 /* Build configuration list for PBXNativeTarget "Microbit Uploader" */;
|
||||||
|
buildPhases = (
|
||||||
|
E9F4FED91D8709980071D783 /* Sources */,
|
||||||
|
E9F4FEDA1D8709980071D783 /* Frameworks */,
|
||||||
|
E9F4FEDB1D8709980071D783 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = "Microbit Uploader";
|
||||||
|
productName = "Microbit Uploader";
|
||||||
|
productReference = E9F4FEDD1D8709980071D783 /* Microbit Uploader.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
E9F4FED51D8709980071D783 /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
LastUpgradeCheck = 0800;
|
||||||
|
ORGANIZATIONNAME = thomasdenney;
|
||||||
|
TargetAttributes = {
|
||||||
|
E9F4FEDC1D8709980071D783 = {
|
||||||
|
CreatedOnToolsVersion = 7.3.1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = E9F4FED81D8709980071D783 /* Build configuration list for PBXProject "Microbit Uploader" */;
|
||||||
|
compatibilityVersion = "Xcode 3.2";
|
||||||
|
developmentRegion = English;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
Base,
|
||||||
|
);
|
||||||
|
mainGroup = E9F4FED41D8709980071D783;
|
||||||
|
productRefGroup = E9F4FEDE1D8709980071D783 /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
E9F4FEDC1D8709980071D783 /* Microbit Uploader */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
E9F4FEDB1D8709980071D783 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
E9F4FEE71D8709980071D783 /* Assets.xcassets in Resources */,
|
||||||
|
E9F4FEEA1D8709980071D783 /* MainMenu.xib in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
E9F4FED91D8709980071D783 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
E9F4FEE51D8709980071D783 /* main.m in Sources */,
|
||||||
|
E930400A1D89620900D931CA /* Uploader.m in Sources */,
|
||||||
|
E9F4FEE21D8709980071D783 /* AppDelegate.m in Sources */,
|
||||||
|
E93040071D895D1F00D931CA /* DirectoryWatcher.m in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXVariantGroup section */
|
||||||
|
E9F4FEE81D8709980071D783 /* MainMenu.xib */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
E9F4FEE91D8709980071D783 /* Base */,
|
||||||
|
);
|
||||||
|
name = MainMenu.xib;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
E9F4FEEC1D8709980071D783 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "-";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
SDKROOT = macosx;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
E9F4FEED1D8709980071D783 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
CODE_SIGN_IDENTITY = "-";
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = macosx;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
E9F4FEEF1D8709980071D783 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
INFOPLIST_FILE = "Microbit Uploader/Info.plist";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "org.thomasdenney.Microbit-Uploader";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
E9F4FEF01D8709980071D783 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
INFOPLIST_FILE = "Microbit Uploader/Info.plist";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "org.thomasdenney.Microbit-Uploader";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
E9F4FED81D8709980071D783 /* Build configuration list for PBXProject "Microbit Uploader" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
E9F4FEEC1D8709980071D783 /* Debug */,
|
||||||
|
E9F4FEED1D8709980071D783 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
E9F4FEEE1D8709980071D783 /* Build configuration list for PBXNativeTarget "Microbit Uploader" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
E9F4FEEF1D8709980071D783 /* Debug */,
|
||||||
|
E9F4FEF01D8709980071D783 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = E9F4FED51D8709980071D783 /* Project object */;
|
||||||
|
}
|
7
clients/macuploader/Microbit Uploader.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:Microbit Uploader.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
6
clients/macuploader/Microbit Uploader/AppDelegate.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
130
clients/macuploader/Microbit Uploader/AppDelegate.m
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#import "AppDelegate.h"
|
||||||
|
#import "DirectoryWatcher.h"
|
||||||
|
#import "Uploader.h"
|
||||||
|
|
||||||
|
@interface AppDelegate ()<DirectoryWatcherDelegate, UploaderDelegate, NSUserNotificationCenterDelegate>
|
||||||
|
|
||||||
|
@property DirectoryWatcher * watcher;
|
||||||
|
@property Uploader * uploader;
|
||||||
|
@property NSStatusItem * menubarItem;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation AppDelegate
|
||||||
|
|
||||||
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||||
|
// Insert code here to initialize your application
|
||||||
|
self.watcher = [[DirectoryWatcher alloc] initWithPath:[self downloadsDirectory]];
|
||||||
|
self.watcher.delegate = self;
|
||||||
|
[self.watcher startWatching];
|
||||||
|
|
||||||
|
self.uploader = [[Uploader alloc] init];
|
||||||
|
self.uploader.delegate = self;
|
||||||
|
|
||||||
|
[NSUserNotificationCenter defaultUserNotificationCenter].delegate = self;
|
||||||
|
|
||||||
|
[self createMenuBarIcon];
|
||||||
|
[self configureVolumeMountNotifications];
|
||||||
|
[self showActiveMicroBits];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
||||||
|
// Insert code here to tear down your application
|
||||||
|
[self.watcher stopWatching];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
[[NSWorkspace sharedWorkspace].notificationCenter removeObserver:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Directory
|
||||||
|
|
||||||
|
- (void)watcher:(DirectoryWatcher *)watcher observedNewFileAtPath:(NSString *)path {
|
||||||
|
NSString * fullPath = [watcher.path stringByAppendingPathComponent:path];
|
||||||
|
if ([self.uploader shouldUploadFileAtPath:fullPath]) {
|
||||||
|
[self.uploader uploadFile:fullPath];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString*)downloadsDirectory {
|
||||||
|
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory, NSUserDomainMask, YES);
|
||||||
|
return paths.firstObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Uploader delegate
|
||||||
|
|
||||||
|
- (void)uploader:(Uploader *)uploader transferredFile:(NSString *)file toMicroBit:(NSString *)microbit {
|
||||||
|
[self showNotification:@"micro:bit upload" withDescription:[NSString stringWithFormat:@"%@ uploaded to %@", file.lastPathComponent, microbit]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)uploader:(Uploader *)uploader failedToTransferFile:(NSString *)file toMicroBit:(NSString *)microbit {
|
||||||
|
[self showNotification:@"micro:bit upload failed" withDescription:[NSString stringWithFormat:@"Couldn't transfer %@ to %@", file.lastPathComponent, microbit]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)showNotification:(NSString*)title withDescription:(NSString*)description {
|
||||||
|
NSUserNotification * notification = [NSUserNotification new];
|
||||||
|
notification.title = title;
|
||||||
|
notification.informativeText = description;
|
||||||
|
notification.soundName = NSUserNotificationDefaultSoundName;
|
||||||
|
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - NSUserNotificationCenterDelegate
|
||||||
|
|
||||||
|
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Volume mount/unmount notification
|
||||||
|
|
||||||
|
- (void)configureVolumeMountNotifications {
|
||||||
|
[[NSWorkspace sharedWorkspace].notificationCenter addObserver:self selector:@selector(volumeMountNotification:) name:NSWorkspaceDidRenameVolumeNotification object:nil];
|
||||||
|
[[NSWorkspace sharedWorkspace].notificationCenter addObserver:self selector:@selector(volumeMountNotification:) name:NSWorkspaceDidMountNotification object:nil];
|
||||||
|
[[NSWorkspace sharedWorkspace].notificationCenter addObserver:self selector:@selector(volumeMountNotification:) name:NSWorkspaceDidUnmountNotification object:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)volumeMountNotification:(NSNotification*)sender {
|
||||||
|
//Delay upadting the menu to give the chance for the disk to fully mount or unmount
|
||||||
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
|
[self showActiveMicroBits];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Menu bar app
|
||||||
|
|
||||||
|
- (void)createMenuBarIcon {
|
||||||
|
self.menubarItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
|
||||||
|
self.menubarItem.button.image = [NSImage imageNamed:@"menubar"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)showActiveMicroBits {
|
||||||
|
NSMenu * menu = [NSMenu new];
|
||||||
|
NSString * countString;
|
||||||
|
NSUInteger count = self.uploader.microBitPaths.count;
|
||||||
|
if (count == 0) {
|
||||||
|
countString = @"No connect micro:bits";
|
||||||
|
}
|
||||||
|
else if (count == 1) {
|
||||||
|
countString = @"1 connected micro:bit";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
countString = [NSString stringWithFormat:@"%lu connected micro:bits", count];
|
||||||
|
}
|
||||||
|
NSMenuItem * microBitCount = [[NSMenuItem alloc] initWithTitle:countString action:nil keyEquivalent:@""];
|
||||||
|
microBitCount.enabled = NO;
|
||||||
|
[menu addItem:microBitCount];
|
||||||
|
|
||||||
|
NSMenuItem * websiteItem = [[NSMenuItem alloc] initWithTitle:@"Editor" action:@selector(launchEditor:) keyEquivalent:@"e"];
|
||||||
|
[menu addItem:websiteItem];
|
||||||
|
|
||||||
|
NSMenuItem * quitItem = [[NSMenuItem alloc] initWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
|
||||||
|
[menu addItem:quitItem];
|
||||||
|
|
||||||
|
self.menubarItem.menu = menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)launchEditor:(id)sender {
|
||||||
|
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://codethemicrobit.com/"]];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"size" : "16x16",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_16x16.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "16x16",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_16x16@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "32x32",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_32x32.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "32x32",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_32x32@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "128x128",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_128x128.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "128x128",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_128x128@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "256x256",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_256x256.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "256x256",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_256x256@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "512x512",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_512x512.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "512x512",
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "icon_512x512@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 574 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 136 KiB |
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
15
clients/macuploader/Microbit Uploader/Assets.xcassets/menubar.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"filename" : "menubar.pdf"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"template-rendering-intent" : "template"
|
||||||
|
}
|
||||||
|
}
|
BIN
clients/macuploader/Microbit Uploader/Assets.xcassets/menubar.imageset/menubar.pdf
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="15G1004" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="macosx"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
|
||||||
|
</dependencies>
|
||||||
|
<objects>
|
||||||
|
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||||
|
<connections>
|
||||||
|
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
|
||||||
|
</connections>
|
||||||
|
</customObject>
|
||||||
|
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||||
|
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||||
|
<customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
|
||||||
|
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||||
|
</objects>
|
||||||
|
</document>
|
24
clients/macuploader/Microbit Uploader/DirectoryWatcher.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@class DirectoryWatcher;
|
||||||
|
|
||||||
|
@protocol DirectoryWatcherDelegate <NSObject>
|
||||||
|
|
||||||
|
- (void)watcher:(DirectoryWatcher*)watcher observedNewFileAtPath:(NSString*)path;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface DirectoryWatcher : NSObject
|
||||||
|
|
||||||
|
- (instancetype)initWithPath:(NSString*)path;
|
||||||
|
|
||||||
|
@property (readonly) NSString * path;
|
||||||
|
|
||||||
|
@property id<DirectoryWatcherDelegate> delegate;
|
||||||
|
|
||||||
|
- (void)startWatching;
|
||||||
|
|
||||||
|
//Automatically called when deallocated
|
||||||
|
- (void)stopWatching;
|
||||||
|
|
||||||
|
@end
|
75
clients/macuploader/Microbit Uploader/DirectoryWatcher.m
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#import "DirectoryWatcher.h"
|
||||||
|
#import <CoreServices/CoreServices.h>
|
||||||
|
|
||||||
|
void callback(ConstFSEventStreamRef streamRef, void * info, size_t numEvents, void * eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]);
|
||||||
|
|
||||||
|
@interface DirectoryWatcher ()
|
||||||
|
|
||||||
|
@property NSString * path;
|
||||||
|
@property NSMutableSet<NSString*>* knownFiles;
|
||||||
|
@property FSEventStreamRef stream;
|
||||||
|
|
||||||
|
- (void)rescanPathWithEvents:(BOOL)sendEvents;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation DirectoryWatcher
|
||||||
|
|
||||||
|
- (instancetype)initWithPath:(NSString *)path {
|
||||||
|
if (!path) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
self.path = path;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
[self stopWatching];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)startWatching {
|
||||||
|
self.knownFiles = [NSMutableSet new];
|
||||||
|
[self rescanPathWithEvents:NO];
|
||||||
|
|
||||||
|
CFStringRef path = (__bridge CFStringRef)(self.path);
|
||||||
|
CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void**)&path, 1, NULL);
|
||||||
|
CFAbsoluteTime latency = 1;
|
||||||
|
FSEventStreamContext context = { 0, (__bridge void * _Nullable)(self), NULL, NULL, NULL };
|
||||||
|
self.stream = FSEventStreamCreate(NULL, &callback, &context, pathsToWatch, kFSEventStreamEventIdSinceNow, latency, kFSEventStreamCreateFlagNone);
|
||||||
|
FSEventStreamScheduleWithRunLoop(self.stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||||
|
FSEventStreamStart(self.stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)stopWatching {
|
||||||
|
if (self.stream) {
|
||||||
|
FSEventStreamStop(self.stream);
|
||||||
|
FSEventStreamInvalidate(self.stream);
|
||||||
|
FSEventStreamRelease(self.stream);
|
||||||
|
self.stream = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)rescanPathWithEvents:(BOOL)sendEvents {
|
||||||
|
NSArray<NSString*>* downloadFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.path error:nil];
|
||||||
|
NSMutableSet<NSString*>* fullSet = [NSMutableSet new];
|
||||||
|
for (NSString * file in downloadFiles) {
|
||||||
|
[fullSet addObject:file];
|
||||||
|
if (![self.knownFiles containsObject:file]) {
|
||||||
|
if (sendEvents) {
|
||||||
|
[self.delegate watcher:self observedNewFileAtPath:file];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.knownFiles = fullSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
void callback(ConstFSEventStreamRef streamRef, void * info, size_t numEvents, void * eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) {
|
||||||
|
DirectoryWatcher * watcher = (__bridge DirectoryWatcher*)info;
|
||||||
|
[watcher rescanPathWithEvents:YES];
|
||||||
|
}
|
36
clients/macuploader/Microbit Uploader/Info.plist
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string></string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.01</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>2</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||||
|
<key>LSUIElement</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>Copyright © 2016 Thomas Denney. All rights reserved.</string>
|
||||||
|
<key>NSMainNibFile</key>
|
||||||
|
<string>MainMenu</string>
|
||||||
|
<key>NSPrincipalClass</key>
|
||||||
|
<string>NSApplication</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
21
clients/macuploader/Microbit Uploader/Uploader.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@class Uploader;
|
||||||
|
|
||||||
|
@protocol UploaderDelegate <NSObject>
|
||||||
|
|
||||||
|
- (void)uploader:(Uploader*)uploader transferredFile:(NSString*)file toMicroBit:(NSString*)microbit;
|
||||||
|
- (void)uploader:(Uploader*)uploader failedToTransferFile:(NSString*)file toMicroBit:(NSString*)microbit;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface Uploader : NSObject
|
||||||
|
|
||||||
|
@property id<UploaderDelegate> delegate;
|
||||||
|
|
||||||
|
- (BOOL)shouldUploadFileAtPath:(NSString*)path;
|
||||||
|
- (NSArray<NSString*>*)microBitPaths;
|
||||||
|
- (void)uploadFile:(NSString*)file;
|
||||||
|
- (void)uploadFile:(NSString*)file toMicroBit:(NSString*)path;
|
||||||
|
|
||||||
|
@end
|
74
clients/macuploader/Microbit Uploader/Uploader.m
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#import "Uploader.h"
|
||||||
|
|
||||||
|
@interface Uploader ()
|
||||||
|
|
||||||
|
@property NSOperationQueue * backgroundCopyQueue;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation Uploader
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
self.backgroundCopyQueue = [NSOperationQueue new];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)shouldUploadFileAtPath:(NSString *)path {
|
||||||
|
//Whilst Safari is downloading the file it appends .download to the name
|
||||||
|
NSRegularExpression * ignoreDownload = [NSRegularExpression regularExpressionWithPattern:@".download$" options:NSRegularExpressionCaseInsensitive error:nil];
|
||||||
|
if ([ignoreDownload numberOfMatchesInString:path.lastPathComponent options:0 range:NSMakeRange(0, path.lastPathComponent.length)] > 0) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Chrome and Firefox create .hex files
|
||||||
|
NSRegularExpression * hexFiles = [NSRegularExpression regularExpressionWithPattern:@".hex$" options:NSRegularExpressionCaseInsensitive error:nil];
|
||||||
|
if ([hexFiles numberOfMatchesInString:path.lastPathComponent options:0 range:NSMakeRange(0, path.lastPathComponent.length)] > 0) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Safari tends to just name files 'Unknown X'
|
||||||
|
NSRegularExpression * unknownFiles = [NSRegularExpression regularExpressionWithPattern:@"^Unknown(( |-)[0-9]+)?" options:NSRegularExpressionCaseInsensitive error:nil];
|
||||||
|
if ([unknownFiles numberOfMatchesInString:path.lastPathComponent options:0 range:NSMakeRange(0, path.lastPathComponent.length)]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray<NSString*>*)microBitPaths {
|
||||||
|
NSArray<NSURL*>* allVolumes = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:nil options:NSVolumeEnumerationSkipHiddenVolumes];
|
||||||
|
NSMutableArray<NSString*>* microbitPaths = [NSMutableArray new];
|
||||||
|
NSRegularExpression * microbitRegex = [NSRegularExpression regularExpressionWithPattern:@"^MICROBIT" options:NSRegularExpressionCaseInsensitive error:nil];
|
||||||
|
for (NSURL * volume in allVolumes) {
|
||||||
|
NSString * lastPathComponent = volume.lastPathComponent;
|
||||||
|
if ([microbitRegex numberOfMatchesInString:lastPathComponent options:0 range:NSMakeRange(0, lastPathComponent.length)] > 0) {
|
||||||
|
[microbitPaths addObject:volume.path];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return microbitPaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)uploadFile:(NSString *)file {
|
||||||
|
for (NSString * microbit in [self microBitPaths]) {
|
||||||
|
[self uploadFile:file toMicroBit:microbit];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)uploadFile:(NSString *)file toMicroBit:(NSString *)path {
|
||||||
|
[self.backgroundCopyQueue addOperationWithBlock:^{
|
||||||
|
NSError * copyError;
|
||||||
|
NSString * destination = [path stringByAppendingPathComponent:file.lastPathComponent];
|
||||||
|
if (![[NSFileManager defaultManager] copyItemAtPath:file toPath:destination error:©Error]) {
|
||||||
|
[self.delegate uploader:self failedToTransferFile:file toMicroBit:path.lastPathComponent];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[self.delegate uploader:self transferredFile:file toMicroBit:path.lastPathComponent];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
5
clients/macuploader/Microbit Uploader/main.m
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
int main(int argc, const char * argv[]) {
|
||||||
|
return NSApplicationMain(argc, argv);
|
||||||
|
}
|
40
clients/macuploader/README.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# micro:bit uploader for OS X
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This project is a clone of the [Windows
|
||||||
|
uploader](https://codethemicrobit.com/uploader), but for OS X. Once launched,
|
||||||
|
the app runs in your menu bar and will automatically deploy any HEX files to
|
||||||
|
your `micro:bit`. Like the Windows version, it is compatible with any browser
|
||||||
|
that can run [codethemicrobit.com](http://codethemicrobit.com).
|
||||||
|
|
||||||
|
## Install the built version
|
||||||
|
|
||||||
|
1. Download the latest `.zip` release from the `Release` directory
|
||||||
|
2. Unzip it
|
||||||
|
3. Drag `Microbit Uploader` to your Applications folder and launch it
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
To build the project you'll need a copy of OS X 10.11 or higher and Xcode 8 or
|
||||||
|
higher (you may be able to build on earlier OSes or versions of Xcode, but this
|
||||||
|
remains untested). Once you have a development environment set up, just build
|
||||||
|
and run `Microbit Uploader.xcodeproj`.
|
||||||
|
|
||||||
|
## Distributing
|
||||||
|
|
||||||
|
1. Open the Xcode project
|
||||||
|
2. Product > Archive
|
||||||
|
3. Export:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
4. You will then have the option of either signing or not-signing the
|
||||||
|
application:
|
||||||
|
|
||||||
|
a) If you have an Apple developer account, select 'Export a Developer
|
||||||
|
ID-signed Application'
|
||||||
|
|
||||||
|
b) If you don't have a developer ID, select 'Export as a macOS App'
|
||||||
|
|
||||||
|
5. Zip the produced app and upload to CDN or equivalent
|
BIN
clients/macuploader/Release/Microbit Uploader v1.0.zip
Normal file
BIN
clients/macuploader/Release/Microbit Uploader v1.01.zip
Normal file
@ -19,10 +19,3 @@
|
|||||||
<link rel="shortcut icon" href="@appLogo@">
|
<link rel="shortcut icon" href="@appLogo@">
|
||||||
<meta name="theme-color" content="@accentColor@">
|
<meta name="theme-color" content="@accentColor@">
|
||||||
|
|
||||||
<style>
|
|
||||||
#root .avatar .avatar-image {
|
|
||||||
background-image: url(https://az851932.vo.msecnd.net/pub/jovrytni/microbit.simplified.svg);
|
|
||||||
background-size: contain;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
</style>
|
|
5
docfiles/target.css
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#root .avatar .avatar-image {
|
||||||
|
background-image: url(https://az851932.vo.msecnd.net/pub/jovrytni/microbit.simplified.svg);
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
13
docfiles/tracking.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<script type="text/javascript">
|
||||||
|
var appInsights=window.appInsights||function(config){
|
||||||
|
function r(config){t[config]=function(){var i=arguments;t.queue.push(function(){t[config].apply(t,i)})}}var t={config:config},u=document,e=window,o="script",s=u.createElement(o),i,f;for(s.src=config.url||"//az416426.vo.msecnd.net/scripts/a/ai.0.js",u.getElementsByTagName(o)[0].parentNode.appendChild(s),t.cookie=u.cookie,t.queue=[],i=["Event","Exception","Metric","PageView","Trace"];i.length;)r("track"+i.pop());return r("setAuthenticatedUserContext"),r("clearAuthenticatedUserContext"),config.disableExceptionTracking||(i="onerror",r("_"+i),f=e[i],e[i]=function(config,r,u,e,o){var s=f&&f(config,r,u,e,o);return s!==!0&&t["_"+i](config,r,u,e,o),s}),t
|
||||||
|
}({
|
||||||
|
instrumentationKey:"e9ae05ca-350b-427a-9775-3ba3f6efabce"
|
||||||
|
});window.appInsights=appInsights;
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
(function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable time_event track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config reset people.set people.set_once people.increment people.append people.union people.track_charge people.clear_charges people.delete_user".split(" ");
|
||||||
|
for(g=0;g<i.length;g++)f(c,i[g]);b._i.push([a,e,d])};b.__SV=1.2;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src="undefined"!==typeof MIXPANEL_CUSTOM_LIB_URL?MIXPANEL_CUSTOM_LIB_URL:"file:"===e.location.protocol&&"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//)?"https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js":"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f)}})(document,window.mixpanel||[]);
|
||||||
|
|
||||||
|
mixpanel.init("762fef19c053a0ea4cec43d2fecae76e");
|
||||||
|
</script>
|
@ -1,3 +1,50 @@
|
|||||||
|

|
||||||
|
|
||||||
|
# About
|
||||||
|
|
||||||
|
### @description A Blocks / Javascript code editor for the micro:bit, a pocket-size computer with 5x5 display, sensors and Bluetooth.
|
||||||
|
|
||||||
|
The [BBC micro:bit](https://www.microbit.co.uk) is a [pocket-size computer](/device) with a 5x5 display of 25 LEDs, Bluetooth and sensors that can be programmed by anyone.
|
||||||
|
The BBC micro:bit was made possible by many [partners](https://www.microbit.co.uk/partners).
|
||||||
|
|
||||||
|
The micro:bit provides an easy and fun introduction to programming and making – switch on, program it to do something fun – wear it, customize it.
|
||||||
|
Just like Arduino, the micro:bit can be connected to and interact with sensors, displays, and other devices.
|
||||||
|
|
||||||
|
* [Read the docs](/docs)
|
||||||
|
|
||||||
|
## [Hardware: The Device](/device)
|
||||||
|
|
||||||
|
The BBC micro:bit is packaged with sensors, radio and other goodies. Learn about the [hardware components](/device) of the micro:bit to make the most of it!
|
||||||
|
|
||||||
|
## Programming: [Blocks](/blocks) or [JavaScript](/javascript)
|
||||||
|
|
||||||
|
You can program the micro:bit using [Blocks](/blocks) or [JavaScript](/javascript) in your web browser via the [micro:bit APIs](/reference):
|
||||||
|
|
||||||
|
```block
|
||||||
|
input.onButtonPressed(Button.A, () => {
|
||||||
|
basic.showString("Hi!");
|
||||||
|
})
|
||||||
|
```
|
||||||
|
```typescript
|
||||||
|
input.onButtonPressed(Button.A, () => {
|
||||||
|
basic.showString("Hi!");
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The editor work in [most modern browsers](/browsers), work [offline](/offline) once loaded and do not require any installation.
|
||||||
|
|
||||||
|
## [Compile and Flash: Your Program!](/device/usb)
|
||||||
|
|
||||||
|
When you have your code ready, you connect your micro:bit to a computer via a USB cable, so it appears as a mounted drive (named MICROBIT).
|
||||||
|
|
||||||
|
Compilation to ARM thumb machine code from [Blocks](/blocks) or [JavaScript](/javascript) happens in the browser. You save the ARM binary
|
||||||
|
program to a file, which you then copy to the micro:bit drive, which flashes the micro:bit device with the new program.
|
||||||
|
|
||||||
|
## Simulator: Test Your Code
|
||||||
|
|
||||||
|
You can run your code using the micro:bit simulator, all within the confines of a web browser.
|
||||||
|
The simulator has support for the LED screen, buttons, as well as compass, accelerometer, and digital I/O pins.
|
||||||
|
|
||||||
```sim
|
```sim
|
||||||
basic.forever(() => {
|
basic.forever(() => {
|
||||||
basic.showString("Hi!");
|
basic.showString("Hi!");
|
||||||
@ -21,41 +68,6 @@ input.onButtonPressed(Button.B, () => {
|
|||||||
. . # . .`);
|
. . # . .`);
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
# About
|
|
||||||
|
|
||||||
### @description A Blocks / Javascript code editor for the micro:bit, a pocket-size computer with 5x5 display, sensors and Bluetooth.
|
|
||||||
|
|
||||||
The [BBC micro:bit](https://www.microbit.co.uk) is a [pocket-size computer](/device) with a 5x5 display of 25 LEDs, Bluetooth and sensors that can be programmed by anyone.
|
|
||||||
The BBC micro:bit was made possible by many [partners](https://www.microbit.co.uk/partners).
|
|
||||||
|
|
||||||
The micro:bit provides an easy and fun introduction to programming and making – switch on, program it to do something fun – wear it, customize it.
|
|
||||||
Just like Arduino, the micro:bit can be connected to and interact with sensors, displays, and other devices.
|
|
||||||
|
|
||||||
## Hardware: The Device
|
|
||||||
|
|
||||||
Learn about the [hardware components](/device) of the micro:bit to make the most of it!
|
|
||||||
|
|
||||||
## Programming: Blocks or JavaScript
|
|
||||||
|
|
||||||
You can program the micro:bit using [Blocks](/blocks) or [JavaScript](/javascript), via the [micro:bit APIs](/reference):
|
|
||||||
|
|
||||||
```blocks
|
|
||||||
input.onButtonPressed(Button.A, () => {
|
|
||||||
basic.showString("Hi!");
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
## Compile and Flash: Your Program!
|
|
||||||
|
|
||||||
When you have your code ready, you connect your micro:bit to a computer via a USB cable, so it appears as a mounted drive (named MICROBIT).
|
|
||||||
|
|
||||||
Compilation to ARM thumb machine code from [Blocks](/blocks) or [JavaScript](/javascript) happens in the browser. You save the ARM binary
|
|
||||||
program to a file, which you then copy to the micro:bit drive, which flashes the micro:bit device with the new program.
|
|
||||||
|
|
||||||
## Simulator: Test Your Code
|
|
||||||
|
|
||||||
You can run your code using the micro:bit simulator, all within the confines of a web browser.
|
|
||||||
The simulator has support for the LED screen, buttons, as well as compass, accelerometer, and digital I/O pins.
|
|
||||||
|
|
||||||
## C++ Runtime
|
## C++ Runtime
|
||||||
|
|
||||||
@ -65,6 +77,15 @@ as well as a set of helper functions (such as displaying a number/image/string o
|
|||||||
The [micro:bit library](/reference) mirrors the functions of the C++ library.
|
The [micro:bit library](/reference) mirrors the functions of the C++ library.
|
||||||
When code is compiled to ARM machine code, the calls to JavaScript micro:bit functions are replaced with calls to the corresponding C++ functions.
|
When code is compiled to ARM machine code, the calls to JavaScript micro:bit functions are replaced with calls to the corresponding C++ functions.
|
||||||
|
|
||||||
## Open Source
|
## [Command Line Tools](/cli)
|
||||||
|
|
||||||
|
Looking to use codethemicrobit.com in your favorite editor? Install the [command line tools](/cli) and get rolling!
|
||||||
|
|
||||||
|
## [Packages](/packages)
|
||||||
|
|
||||||
|
Create, edit and distribute your own blocks and JavaScript using [packages](/packages). Packages are hosted on GitHub and may be written
|
||||||
|
using C++, JavaScript and/or ARM thumb.
|
||||||
|
|
||||||
|
## [Open Source](/open-source)
|
||||||
|
|
||||||
The code for the micro:bit is [open source](/open-source) on GitHub. Contributors are welcome!
|
The code for the micro:bit is [open source](/open-source) on GitHub. Contributors are welcome!
|
||||||
|
104
docs/browsers.md
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
# Unsupported configuration
|
||||||
|
|
||||||
|
[codethemicrobit.com](https://codethemicrobit.com) doesn't currently support
|
||||||
|
your browser or operating system. The following configurations are supported:
|
||||||
|
|
||||||
|
## Windows
|
||||||
|
|
||||||
|
You need one of these browsers running on Windows 7, Windows 8, Windows 8.1, or
|
||||||
|
Windows 10:
|
||||||
|
|
||||||
|
* Internet Explorer 11
|
||||||
|
* Microsoft Edge
|
||||||
|
* Google Chrome
|
||||||
|
* Mozilla Firefox
|
||||||
|
|
||||||
|
## Mac
|
||||||
|
|
||||||
|
You need one of these browsers running on OS X 10.9 Mavericks, OS X 10.10
|
||||||
|
Yosemite, OS X 10.11 El Capitan, or macOS 10.12 Sierra:
|
||||||
|
|
||||||
|
* Safari
|
||||||
|
* Google Chrome
|
||||||
|
* Mozilla Firefox
|
||||||
|
|
||||||
|
## Linux
|
||||||
|
|
||||||
|
If you're using a Raspberry Pi, please see [the documentation
|
||||||
|
here](/raspberry-pi).
|
||||||
|
|
||||||
|
You need to be running a Linux distribution recent enough to run the most recent
|
||||||
|
version of one of the following:
|
||||||
|
|
||||||
|
* Google Chrome, or Chromium
|
||||||
|
* Mozilla Firefox, Iceweasel, or Seamonkey
|
||||||
|
|
||||||
|
## How to check your OS or browser
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
* Click on the Start menu
|
||||||
|
* Type 'System'
|
||||||
|
* Click on the app called 'System'
|
||||||
|
* The version of Windows you are using will be displayed:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Mac
|
||||||
|
|
||||||
|
* Click on the Apple icon in the top left
|
||||||
|
* Click on 'About this Mac'
|
||||||
|
* This window will be displayed:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Internet Explorer
|
||||||
|
|
||||||
|
* Click on the Settings icon in the top right
|
||||||
|
* Click 'About Internet Explorer'
|
||||||
|
* This window will be displayed:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Edge
|
||||||
|
|
||||||
|
Edge automatically updates, so you should always be using the latest version
|
||||||
|
|
||||||
|
* Click on the menu icon in the top right (three dots)
|
||||||
|
* Scroll to the bottom
|
||||||
|
* Information similar to the following will be displayed:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Google Chrome
|
||||||
|
|
||||||
|
Google Chrome automatically updates, so you should always be using the latest version
|
||||||
|
|
||||||
|
* Click on the menu icon in the top right (three dots)
|
||||||
|
* Click Help, and About Google Chrome
|
||||||
|
* Information similar to the following will be displayed:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Firefox
|
||||||
|
|
||||||
|
Firefox automatically updates, so you should always be using the latest version
|
||||||
|
|
||||||
|
* Click on the menu icon in the top right (three horizontal lines)
|
||||||
|
* Click the question mark icon (help button)
|
||||||
|
* Click 'About Firefox'
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Safari
|
||||||
|
|
||||||
|
Safari updates when your operating system updates, so if you are using the
|
||||||
|
latest version of OS X then you'll be using the latest version of Safari.
|
||||||
|
|
||||||
|
* Click on the Safari menu in the top left
|
||||||
|
* Click 'About Safari'
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
IT administrators should check which browser versions are supported
|
||||||
|
[here](/browsers/technical).
|
16
docs/browsers/linux.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Recommended browser for Linux
|
||||||
|
|
||||||
|
As you are using Linux, it is recommended that you use [Mozilla
|
||||||
|
Firefox][firefox] or [Google Chrome][chrome].
|
||||||
|
|
||||||
|
Please see [here][technical] for technical information on which browsers are
|
||||||
|
supported, or [here][versions] to check which version you are using.
|
||||||
|
|
||||||
|
[edge]: https://www.microsoft.com/en-us/windows/microsoft-edge
|
||||||
|
[ie]: https://www.microsoft.com/en-us/download/internet-explorer.aspx
|
||||||
|
[firefox]: https://www.mozilla.org/en-US/firefox/new/
|
||||||
|
[chrome]: https://www.google.com/chrome/
|
||||||
|
[opera]: https://www.opera.com
|
||||||
|
[safari]: http://www.apple.com/safari/
|
||||||
|
[technical]: /browsers/technical
|
||||||
|
[versions]: /browsers
|
16
docs/browsers/mac.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Recommended browser for Mac
|
||||||
|
|
||||||
|
As you are using a Mac, it is recommended that you use [Safari][]. Alternatively,
|
||||||
|
[Google Chrome][chrome] and [Mozilla Firefox][firefox] are also supported.
|
||||||
|
|
||||||
|
Please see [here][technical] for technical information on which browsers are
|
||||||
|
supported, or [here][versions] to check which version you are using.
|
||||||
|
|
||||||
|
[edge]: https://www.microsoft.com/en-us/windows/microsoft-edge
|
||||||
|
[ie]: https://www.microsoft.com/en-us/download/internet-explorer.aspx
|
||||||
|
[firefox]: https://www.mozilla.org/en-US/firefox/new/
|
||||||
|
[chrome]: https://www.google.com/chrome/
|
||||||
|
[opera]: https://www.opera.com
|
||||||
|
[safari]: http://www.apple.com/safari/
|
||||||
|
[technical]: /browsers/technical
|
||||||
|
[versions]: /browsers
|
36
docs/browsers/technical.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# Technical information about browser support
|
||||||
|
|
||||||
|
[codethemicrobit.com][] requires that you use a recent version of a modern
|
||||||
|
browser, such as Microsoft Edge, Google Chrome, Mozilla Firefox, Safari, Opera,
|
||||||
|
or IE11. This is because the editor uses modern web technologies such as [web
|
||||||
|
workers][] to enable compiling [TypeScript][] in the browser, or the using the
|
||||||
|
same [Monaco][] editor that powers [Visual Studio Code][].
|
||||||
|
|
||||||
|
[codethemicrobit.com]: https://codethemicrobit.com
|
||||||
|
[web workers]: http://www.w3.org/TR/workers/
|
||||||
|
[typescript]: http://www.typescriptlang.org
|
||||||
|
[monaco]: https://microsoft.github.io/monaco-editor/
|
||||||
|
[visual studio code]: http://code.visualstudio.com
|
||||||
|
|
||||||
|
Most modern browsers automatically update themselves, but in some environments
|
||||||
|
such as schools these automatic updates are disabled for security. **We
|
||||||
|
strongly recommend that you use the most recent version of any of these
|
||||||
|
browsers**, but if you can't then you must use at least:
|
||||||
|
|
||||||
|
| Browser | Minimum version | Release date | Windows | Mac |
|
||||||
|
| ----------------- | --------------- | -------------- | ----------- | ---------- |
|
||||||
|
| Edge | 12 | March 2015 | Windows 10+ | N/A |
|
||||||
|
| Internet Explorer | 11 | October 2013 | Windows 7+ | N/A |
|
||||||
|
| Mozilla Firefox | 31 ESR | July 2014 | Windows XP+ | OS X 10.6+ |
|
||||||
|
| Google Chrome | 38 | October 2014 | Windows XP+ | OS X 10.6+ |
|
||||||
|
| Safari | 9 | September 2015 | N/A | OS X 10.9+ |
|
||||||
|
| Opera | 21 | May 2014 | Windows 7+ | OS X 10.9+ |
|
||||||
|
|
||||||
|
|
||||||
|
Please see our information for which browsers are recommended for [Windows][],
|
||||||
|
[Mac][], [Linux][], or [Raspberry Pi][].
|
||||||
|
|
||||||
|
[Windows]: /browsers/windows
|
||||||
|
[Mac]: /browsers/mac
|
||||||
|
[Linux]: /browsers/linux
|
||||||
|
[Raspberry Pi]: /raspberry-pi
|
18
docs/browsers/windows.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Recommended browser for Windows
|
||||||
|
|
||||||
|
We recommend [Microsoft Edge][edge] if you are running Windows 10, but users on
|
||||||
|
Windows 7 or higher can use [Internet Explorer 11][ie] or recent versions of
|
||||||
|
[Mozilla Firefox][firefox], [Google Chrome][chrome], or [Opera][opera].
|
||||||
|
|
||||||
|
|
||||||
|
Please see [here][technical] for technical information on which browsers are
|
||||||
|
supported, or [here][versions] to check which version you are using.
|
||||||
|
|
||||||
|
[edge]: https://www.microsoft.com/en-us/windows/microsoft-edge
|
||||||
|
[ie]: https://www.microsoft.com/en-us/download/internet-explorer.aspx
|
||||||
|
[firefox]: https://www.mozilla.org/en-US/firefox/new/
|
||||||
|
[chrome]: https://www.google.com/chrome/
|
||||||
|
[opera]: https://www.opera.com
|
||||||
|
[safari]: http://www.apple.com/safari/
|
||||||
|
[technical]: /browsers/technical
|
||||||
|
[versions]: /browsers
|
@ -1,6 +1,4 @@
|
|||||||
# Running programs on your micro:bit
|
# Uploading programs on your micro:bit
|
||||||
|
|
||||||
How to compile, transfer, and run a program on your micro:bit.
|
|
||||||
|
|
||||||
While you're writing and testing your programs, you'll mostly be [running them
|
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
|
in the simulator](/device/simulator), but once you've finished your program you
|
||||||
@ -12,169 +10,22 @@ The basic steps are:
|
|||||||
2. Click **Download** and download the `.hex` file
|
2. Click **Download** and download the `.hex` file
|
||||||
3. Copy the `.hex` file from your computer onto the micro:bit drive
|
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:
|
## Instructions
|
||||||
|
|
||||||
* A-Male to Micro USB cable to connect your computer to your micro:bit. This is
|
Pick the instructions for your operating system and browser:
|
||||||
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
|
* [Windows - Microsoft Edge](/device/usb/windows-edge)
|
||||||
|
* [Windows - Internet Explorer](/device/usb/windows-ie)
|
||||||
|
* [Windows - Chrome](/device/usb/windows-chrome)
|
||||||
|
* [Windows - Firefox](/device/usb/windows-firefox)
|
||||||
|
* [Mac - Safari](/device/usb/mac-safari)
|
||||||
|
* [Mac - Chrome](/device/usb/mac-chrome)
|
||||||
|
* [Mac - Firefox](/device/usb/mac-firefox)
|
||||||
|
|
||||||
First, connect the micro:bit:
|
### ~hint
|
||||||
|
|
||||||
1. Connect the small end of the USB cable to the micro USB port on your micro:bit.
|
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshooting).
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
**Windows**
|
|
||||||
|
|
||||||

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

|
|
||||||
|
|
||||||
## Step 2: Download your program
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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**.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Drag and drop the `.hex` file from the download folder onto the `MICROBIT` drive.
|
|
||||||
|
|
||||||
#### Firefox
|
|
||||||
|
|
||||||
A window will appear asking whether you want to save or open the `.hex` file.
|
|
||||||
Select **Save File** and then select **OK**.
|
|
||||||
|
|
||||||

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

|
|
||||||
|
|
||||||
Drag and drop the `.hex` file from the download folder onto the `MICROBIT` drive.
|
|
||||||
|
|
||||||
#### 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
|
|
||||||
|
|
||||||
#### Safari
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
* 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**.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
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 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.
|
|
||||||
|
|
||||||
The errors may look like this:
|
|
||||||
|
|
||||||
**Windows**
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
**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`.
|
|
||||||
|
|
||||||
### See also
|
|
||||||
|
|
||||||
[Run code in a browser](/device/simulator)
|
|
||||||
|
|
||||||
|
### ~
|
||||||
|
69
docs/device/usb/mac-chrome.md
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# Uploading from Chrome for Mac
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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 or later, or a Mac running OS X 10.6 or later
|
||||||
|
|
||||||
|
## Step 1: Connect your micro:bit to your computer
|
||||||
|
|
||||||
|
First, connect the micro:bit:
|
||||||
|
|
||||||
|
1. Connect the small end of the USB cable to the micro USB port on your 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Step 2: Download your program
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
* Once you've found the folder containing your `.hex` file, drag and drop it
|
||||||
|
onto your `MICROBIT` drive
|
||||||
|
* 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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
### ~hint
|
||||||
|
|
||||||
|
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshooting).
|
||||||
|
|
||||||
|
### ~
|
71
docs/device/usb/mac-firefox.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# Uploading from Firefox for Mac
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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 or later, or a Mac running OS X 10.6 or later
|
||||||
|
|
||||||
|
## Step 1: Connect your micro:bit to your computer
|
||||||
|
|
||||||
|
First, connect the micro:bit:
|
||||||
|
|
||||||
|
1. Connect the small end of the USB cable to the micro USB port on your 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Step 2: Download your program
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|

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

|
||||||
|
|
||||||
|
## Step 3: Transfer the file to your micro:bit
|
||||||
|
|
||||||
|
* Once you've found the folder containing your `.hex` file, drag and drop it
|
||||||
|
onto your `MICROBIT` drive
|
||||||
|
* 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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### ~hint
|
||||||
|
|
||||||
|
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshooting).
|
||||||
|
|
||||||
|
### ~
|
68
docs/device/usb/mac-safari.md
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
# Uploading from Safari for Mac
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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 or later, or a Mac running OS X 10.6 or later
|
||||||
|
|
||||||
|
## Step 1: Connect your micro:bit to your computer
|
||||||
|
|
||||||
|
First, connect the micro:bit:
|
||||||
|
|
||||||
|
1. Connect the small end of the USB cable to the micro USB port on your 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Step 2: Download your program
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Step 3: Transfer the file to your micro:bit
|
||||||
|
|
||||||
|
* Once you've found the folder containing your `.hex` file, drag and drop it
|
||||||
|
onto your `MICROBIT` drive
|
||||||
|
* 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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
### ~hint
|
||||||
|
|
||||||
|
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshooting).
|
||||||
|
|
||||||
|
### ~
|
24
docs/device/usb/troubleshooting.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Troubleshooting Transfer
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
The errors may look like this:
|
||||||
|
|
||||||
|
**Windows**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**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`.
|
79
docs/device/usb/windows-chrome.md
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# Uploading from Chrome for Windows
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
### ~hint
|
||||||
|
|
||||||
|
You can use the [micro:bit uploader](/uploader) to automatically deploy ``.hex`` files to your micro:bit!
|
||||||
|

|
||||||
|
|
||||||
|
### ~
|
||||||
|
|
||||||
|
## 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 or later, or a Mac running OS X 10.6 or later
|
||||||
|
|
||||||
|
## Step 1: Connect your micro:bit to your computer
|
||||||
|
|
||||||
|
First, connect the micro:bit:
|
||||||
|
|
||||||
|
1. Connect the small end of the USB cable to the micro USB port on your 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Step 2: Download your program
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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**.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Drag and drop the `.hex` file from the download folder onto the `MICROBIT` drive.
|
||||||
|
|
||||||
|
## Step 3: Transfer the file to your micro:bit
|
||||||
|
|
||||||
|
* Once you've found the folder containing your `.hex` file, drag and drop it
|
||||||
|
onto your `MICROBIT` drive
|
||||||
|
* 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.
|
||||||
|
|
||||||
|
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 program will still run if the micro:bit is powered by battery.
|
||||||
|
|
||||||
|
### ~hint
|
||||||
|
|
||||||
|
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshooting).
|
||||||
|
|
||||||
|
### ~
|
89
docs/device/usb/windows-edge.md
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
# Uploading from Edge on Windows
|
||||||
|
|
||||||
|
How to compile, transfer, and run a program on your micro:bit on **Microsoft Edge**.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
### ~hint
|
||||||
|
|
||||||
|
You can use the [micro:bit uploader](/uploader) to automatically deploy ``.hex`` files to your micro:bit!
|
||||||
|

|
||||||
|
|
||||||
|
### ~
|
||||||
|
|
||||||
|
## 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 or later, or a Mac running OS X 10.6 or later
|
||||||
|
|
||||||
|
## Step 1: Connect your micro:bit to your computer
|
||||||
|
|
||||||
|
First, connect the micro:bit:
|
||||||
|
|
||||||
|
1. Connect the small end of the USB cable to the micro USB port on your 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Step 2: Download your program
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Step 3: Transfer the file to your 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.
|
||||||
|
|
||||||
|
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 program will still run if the micro:bit is powered by battery.
|
||||||
|
|
||||||
|
If you want to save time, you can use the [micro:bit uploader](/uploader) to
|
||||||
|
automatically deploy hex files to your micro:bit. It works on Windows and is
|
||||||
|
compatible with any browser.
|
||||||
|
|
||||||
|
### ~hint
|
||||||
|
|
||||||
|
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshooting).
|
||||||
|
|
||||||
|
### ~
|
86
docs/device/usb/windows-firefox.md
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
# Uploading from Firefox on Windows
|
||||||
|
|
||||||
|
How to compile, transfer, and run a program on your micro:bit on **Firefox for Windows**.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
### ~hint
|
||||||
|
|
||||||
|
You can use the [micro:bit uploader](/uploader) to automatically deploy ``.hex`` files to your micro:bit!
|
||||||
|

|
||||||
|
|
||||||
|
### ~
|
||||||
|
|
||||||
|
## 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 or later, or a Mac running OS X 10.6 or later
|
||||||
|
|
||||||
|
## Step 1: Connect your micro:bit to your computer
|
||||||
|
|
||||||
|
First, connect the micro:bit:
|
||||||
|
|
||||||
|
1. Connect the small end of the USB cable to the micro USB port on your 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Step 2: Download your program
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
A window will appear asking whether you want to save or open the `.hex` file.
|
||||||
|
Select **Save File** and then select **OK**.
|
||||||
|
|
||||||
|

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

|
||||||
|
|
||||||
|
Drag and drop the `.hex` file from the download folder onto the `MICROBIT` drive.
|
||||||
|
## Step 3: Transfer the file to your 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.
|
||||||
|
|
||||||
|
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 program will still run if the micro:bit is powered by battery.
|
||||||
|
|
||||||
|
### ~hint
|
||||||
|
|
||||||
|
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshooting).
|
||||||
|
|
||||||
|
### ~
|
86
docs/device/usb/windows-ie.md
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
# Uploading from Internet Explorer on Windows
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
### ~hint
|
||||||
|
|
||||||
|
You can use the [micro:bit uploader](/uploader) to automatically deploy ``.hex`` files to your micro:bit!
|
||||||
|

|
||||||
|
|
||||||
|
### ~
|
||||||
|
|
||||||
|
## 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 or later, or a Mac running OS X 10.6 or later
|
||||||
|
|
||||||
|
## Step 1: Connect your micro:bit to your computer
|
||||||
|
|
||||||
|
First, connect the micro:bit:
|
||||||
|
|
||||||
|
1. Connect the small end of the USB cable to the micro USB port on your 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Step 2: Download your program
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Step 3: Transfer the file to your 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**.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
### ~hint
|
||||||
|
|
||||||
|
Transfer not working? See some [troubleshooting tips](/device/usb/troubleshooting).
|
||||||
|
|
||||||
|
### ~
|
@ -58,7 +58,9 @@ After running this simulation several seconds by moving the micro:bit side to si
|
|||||||

|

|
||||||
|
|
||||||
### ~
|
### ~
|
||||||
Finally, you must open the Excel CSV file by clicking on the data.xls file that was downloaded to Downloads Folder.
|
|
||||||
|
Finally, you must open the Excel CSV file by clicking on the `data.csv` file
|
||||||
|
that was downloaded to Downloads Folder.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
29
docs/raspberry-pi.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Raspberry Pi and Raspbian
|
||||||
|
|
||||||
|
It is possible to run the web editor or [command line interface](/cli) from Raspbian on Raspberry Pi 2 or 3.
|
||||||
|
|
||||||
|
## Web editor
|
||||||
|
|
||||||
|
The web editor requires to install IceWeasel (Firefox) as the built-in browser cannot handle it.
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt-get install iceweasel
|
||||||
|
```
|
||||||
|
|
||||||
|
Once installed simply navigate to https://codethemicrobit.com or type
|
||||||
|
|
||||||
|
```
|
||||||
|
firefox https://codethemicrobit.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## Command line
|
||||||
|
|
||||||
|
The PXT command line also works on Raspbian and allows to run a local server and/or edit programs from any text editor.
|
||||||
|
|
||||||
|
* Node.JS 6.0 needs installed
|
||||||
|
|
||||||
|
To install all the tools,
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -s https://raw.githubusercontent.com/Microsoft/pxt-rpi/master/install.sh | sh -
|
||||||
|
```
|
BIN
docs/static/configurations/chrome-version.png
vendored
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
docs/static/configurations/edge-version.png
vendored
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
docs/static/configurations/firefox-version.png
vendored
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
docs/static/configurations/ie-version.png
vendored
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
docs/static/configurations/osx-version.png
vendored
Normal file
After Width: | Height: | Size: 128 KiB |
BIN
docs/static/configurations/safari-version.png
vendored
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
docs/static/configurations/windows-version.png
vendored
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
docs/static/mb/device/pano.jpg
vendored
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
docs/static/mb/device/usb-generic.jpg
vendored
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
docs/static/mb/device/usb-mac.jpg
vendored
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
docs/static/mb/device/usb-osx-chrome.png
vendored
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 30 KiB |
BIN
docs/static/mb/device/usb-osx-firefox-1.jpg
vendored
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
docs/static/mb/device/usb-osx-firefox-1.png
vendored
Before Width: | Height: | Size: 102 KiB |
BIN
docs/static/mb/device/usb-thin.jpg
vendored
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
docs/static/mb/device/usb-windows-chrome.png
vendored
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 54 KiB |
BIN
docs/static/mb/device/usb-windows-edge-1.png
vendored
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 24 KiB |
BIN
docs/static/mb/device/usb-windows-edge-2.png
vendored
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 18 KiB |
BIN
docs/static/mb/device/usb-windows-firefox-1.png
vendored
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 6.9 KiB |
BIN
docs/static/mb/device/usb-windows-firefox-2.jpg
vendored
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
docs/static/mb/device/usb-windows-firefox-2.png
vendored
Before Width: | Height: | Size: 120 KiB |
BIN
docs/static/mb/device/usb-windows-ie11-1.png
vendored
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 10 KiB |
BIN
docs/static/mb/device/usb-windows-ie11-2.png
vendored
Before Width: | Height: | Size: 159 KiB After Width: | Height: | Size: 10 KiB |
BIN
docs/static/mb/device/usb-windows-sendto.jpg
vendored
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 50 KiB |
@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"bluetooth": "Support for additional Bluetooth services.",
|
|
||||||
"bluetooth.onBluetoothConnected": "Register code to run when the micro:bit is connected to over Bluetooth",
|
"bluetooth.onBluetoothConnected": "Register code to run when the micro:bit is connected to over Bluetooth",
|
||||||
"bluetooth.onBluetoothConnected|param|body": "Code to run when a Bluetooth connection is established",
|
"bluetooth.onBluetoothConnected|param|body": "Code to run when a Bluetooth connection is established",
|
||||||
"bluetooth.onBluetoothDisconnected": "Register code to run when a bluetooth connection to the micro:bit is lost",
|
"bluetooth.onBluetoothDisconnected": "Register code to run when a bluetooth connection to the micro:bit is lost",
|
||||||
@ -10,6 +9,7 @@
|
|||||||
"bluetooth.startLEDService": "Starts the Bluetooth LED service",
|
"bluetooth.startLEDService": "Starts the Bluetooth LED service",
|
||||||
"bluetooth.startMagnetometerService": "Starts the Bluetooth magnetometer service",
|
"bluetooth.startMagnetometerService": "Starts the Bluetooth magnetometer service",
|
||||||
"bluetooth.startTemperatureService": "Starts the Bluetooth temperature service",
|
"bluetooth.startTemperatureService": "Starts the Bluetooth temperature service",
|
||||||
|
"bluetooth.startUartService": "Starts the Bluetooth UART service",
|
||||||
"bluetooth.uartRead": "Reads from the Bluetooth UART service buffer, returning its contents when the specified delimiter character is encountered.",
|
"bluetooth.uartRead": "Reads from the Bluetooth UART service buffer, returning its contents when the specified delimiter character is encountered.",
|
||||||
"bluetooth.uartWrite": "Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device."
|
"bluetooth.uartWrite": "Writes to the Bluetooth UART service buffer. From there the data is transmitted over Bluetooth to a connected device."
|
||||||
}
|
}
|
@ -7,6 +7,7 @@
|
|||||||
"bluetooth.startLEDService|block": "bluetooth led service",
|
"bluetooth.startLEDService|block": "bluetooth led service",
|
||||||
"bluetooth.startMagnetometerService|block": "bluetooth magnetometer service",
|
"bluetooth.startMagnetometerService|block": "bluetooth magnetometer service",
|
||||||
"bluetooth.startTemperatureService|block": "bluetooth temperature service",
|
"bluetooth.startTemperatureService|block": "bluetooth temperature service",
|
||||||
|
"bluetooth.startUartService|block": "bluetooth uart service",
|
||||||
"bluetooth.uartRead|block": "bluetooth uart read %del=bluetooth_uart_delimiter_conv",
|
"bluetooth.uartRead|block": "bluetooth uart read %del=bluetooth_uart_delimiter_conv",
|
||||||
"bluetooth.uartWrite|block": "bluetooth uart write %data",
|
"bluetooth.uartWrite|block": "bluetooth uart write %data",
|
||||||
"bluetooth|block": "bluetooth"
|
"bluetooth|block": "bluetooth"
|
||||||
|
@ -141,7 +141,6 @@ namespace radio {
|
|||||||
*/
|
*/
|
||||||
//% help=radio/received-number-at
|
//% help=radio/received-number-at
|
||||||
//% weight=45 debug=true
|
//% weight=45 debug=true
|
||||||
//% blockId=radio_datagram_received_number_at block="radio receive number|at %VALUE" blockGap=8
|
|
||||||
int receivedNumberAt(int index) {
|
int receivedNumberAt(int index) {
|
||||||
if (radioEnable() != MICROBIT_OK) return 0;
|
if (radioEnable() != MICROBIT_OK) return 0;
|
||||||
if (0 <= index && index < packet.length() / 4) {
|
if (0 <= index && index < packet.length() / 4) {
|
||||||
|
3
libs/microbit-radio/shims.d.ts
vendored
@ -46,8 +46,7 @@ declare namespace radio {
|
|||||||
* @param index index of the number to read from 0 to 3. 1 eg
|
* @param index index of the number to read from 0 to 3. 1 eg
|
||||||
*/
|
*/
|
||||||
//% help=radio/received-number-at
|
//% help=radio/received-number-at
|
||||||
//% weight=45 debug=true
|
//% weight=45 debug=true shim=radio::receivedNumberAt
|
||||||
//% blockId=radio_datagram_received_number_at block="radio receive number|at %VALUE" blockGap=8 shim=radio::receivedNumberAt
|
|
||||||
function receivedNumberAt(index: number): number;
|
function receivedNumberAt(index: number): number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
"control": "Runtime and event utilities.",
|
"control": "Runtime and event utilities.",
|
||||||
"control.inBackground": "Schedules code that run in the background.",
|
"control.inBackground": "Schedules code that run in the background.",
|
||||||
"control.reset": "Resets the BBC micro:bit.",
|
"control.reset": "Resets the BBC micro:bit.",
|
||||||
|
"control.waitMicros": "Blocks the current fiber for the given microseconds",
|
||||||
|
"control.waitMicros|param|micros": "number of micro-seconds to wait. eg: 4",
|
||||||
"game": "A single-LED sprite game engine",
|
"game": "A single-LED sprite game engine",
|
||||||
"game.addScore": "Adds points to the current score",
|
"game.addScore": "Adds points to the current score",
|
||||||
"game.addScore|param|points": "amount of points to change, eg: 1",
|
"game.addScore|param|points": "amount of points to change, eg: 1",
|
||||||
@ -52,9 +54,12 @@
|
|||||||
"input.onLogoDown|param|body": "TODO",
|
"input.onLogoDown|param|body": "TODO",
|
||||||
"input.onLogoUp": "Attaches code to run when the logo is oriented upwards and the board is vertical.",
|
"input.onLogoUp": "Attaches code to run when the logo is oriented upwards and the board is vertical.",
|
||||||
"input.onLogoUp|param|body": "TODO",
|
"input.onLogoUp|param|body": "TODO",
|
||||||
"input.onPinPressed": "Do something when a pin(``P0``, ``P1`` or both ``P2``) is pressed.",
|
"input.onPinPressed": "Do something when a pin is pressed.",
|
||||||
"input.onPinPressed|param|body": "TODO",
|
"input.onPinPressed|param|body": "the code to run when the pin is pressed",
|
||||||
"input.onPinPressed|param|name": "TODO",
|
"input.onPinPressed|param|name": "the pin that needs to be pressed",
|
||||||
|
"input.onPinReleased": "Do something when a pin is released.",
|
||||||
|
"input.onPinReleased|param|body": "the code to run when the pin is released",
|
||||||
|
"input.onPinReleased|param|name": "the pin that needs to be released",
|
||||||
"input.onScreenDown": "Attaches code to run when the screen is facing down.",
|
"input.onScreenDown": "Attaches code to run when the screen is facing down.",
|
||||||
"input.onScreenDown|param|body": "TODO",
|
"input.onScreenDown|param|body": "TODO",
|
||||||
"input.onScreenUp": "Attaches code to run when the screen is facing up.",
|
"input.onScreenUp": "Attaches code to run when the screen is facing up.",
|
||||||
@ -152,6 +157,8 @@
|
|||||||
"pins.setPull": "Configures the pull of this pin.",
|
"pins.setPull": "Configures the pull of this pin.",
|
||||||
"pins.setPull|param|name": "pin to set the pull mode on",
|
"pins.setPull|param|name": "pin to set the pull mode on",
|
||||||
"pins.setPull|param|pull": "one of the mbed pull configurations: PullUp, PullDown, PullNone ",
|
"pins.setPull|param|pull": "one of the mbed pull configurations: PullUp, PullDown, PullNone ",
|
||||||
|
"pins.spiWrite": "Write to the SPI slave and return the response",
|
||||||
|
"pins.spiWrite|param|value": "Data to be sent to the SPI slave",
|
||||||
"serial": "Reading and writing data over a serial connection.",
|
"serial": "Reading and writing data over a serial connection.",
|
||||||
"serial.readLine": "Reads a line of text from the serial port.",
|
"serial.readLine": "Reads a line of text from the serial port.",
|
||||||
"serial.redirect": "Dynamically configuring the serial instance to use pins other than USBTX and USBRX.",
|
"serial.redirect": "Dynamically configuring the serial instance to use pins other than USBTX and USBRX.",
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"basic|block": "basic",
|
"basic|block": "basic",
|
||||||
"control.inBackground|block": "run in background",
|
"control.inBackground|block": "run in background",
|
||||||
"control.reset|block": "reset",
|
"control.reset|block": "reset",
|
||||||
|
"control.waitMicros|block": "wait (µs)%micros",
|
||||||
"control|block": "control",
|
"control|block": "control",
|
||||||
"game.addScore|block": "change score by|%points",
|
"game.addScore|block": "change score by|%points",
|
||||||
"game.gameOver|block": "game over",
|
"game.gameOver|block": "game over",
|
||||||
@ -28,7 +29,8 @@
|
|||||||
"input.magneticForce|block": "magnetic force (µT)|%NAME",
|
"input.magneticForce|block": "magnetic force (µT)|%NAME",
|
||||||
"input.onButtonPressed|block": "on button|%NAME|pressed",
|
"input.onButtonPressed|block": "on button|%NAME|pressed",
|
||||||
"input.onGesture|block": "on |%NAME",
|
"input.onGesture|block": "on |%NAME",
|
||||||
"input.onPinPressed|block": "on pin|%NAME|pressed",
|
"input.onPinPressed|block": "on pin %NAME|pressed",
|
||||||
|
"input.onPinReleased|block": "on pin %NAME|released",
|
||||||
"input.pinIsPressed|block": "pin %NAME|is pressed",
|
"input.pinIsPressed|block": "pin %NAME|is pressed",
|
||||||
"input.rotation|block": "rotation (°)|%NAME",
|
"input.rotation|block": "rotation (°)|%NAME",
|
||||||
"input.runningTime|block": "running time (ms)",
|
"input.runningTime|block": "running time (ms)",
|
||||||
@ -41,6 +43,7 @@
|
|||||||
"led.point|block": "point|x %x|y %y",
|
"led.point|block": "point|x %x|y %y",
|
||||||
"led.setBrightness|block": "set brightness %value",
|
"led.setBrightness|block": "set brightness %value",
|
||||||
"led.stopAnimation|block": "stop animation",
|
"led.stopAnimation|block": "stop animation",
|
||||||
|
"led.toggle|block": "toggle|x %x|y %y",
|
||||||
"led.unplot|block": "unplot|x %x|y %y",
|
"led.unplot|block": "unplot|x %x|y %y",
|
||||||
"led|block": "led",
|
"led|block": "led",
|
||||||
"music.beat|block": "%fraction|beat",
|
"music.beat|block": "%fraction|beat",
|
||||||
@ -65,6 +68,7 @@
|
|||||||
"pins.servoSetPulse|block": "servo set pulse|pin %value|to (µs) %micros",
|
"pins.servoSetPulse|block": "servo set pulse|pin %value|to (µs) %micros",
|
||||||
"pins.servoWritePin|block": "servo write|pin %name|to %value",
|
"pins.servoWritePin|block": "servo write|pin %name|to %value",
|
||||||
"pins.setPull|block": "set pull|pin %pin|to %pull",
|
"pins.setPull|block": "set pull|pin %pin|to %pull",
|
||||||
|
"pins.spiWrite|block": "spi write %value",
|
||||||
"pins|block": "pins",
|
"pins|block": "pins",
|
||||||
"serial.readLine|block": "serial read line",
|
"serial.readLine|block": "serial read line",
|
||||||
"serial.redirect|block": "serial redirect to|TX %tx|RX %rx|at baud rate %rate",
|
"serial.redirect|block": "serial redirect to|TX %tx|RX %rx|at baud rate %rate",
|
||||||
|
@ -8,6 +8,7 @@ namespace control {
|
|||||||
* Returns the value of a C++ runtime constant
|
* Returns the value of a C++ runtime constant
|
||||||
*/
|
*/
|
||||||
//% weight=2 weight=19 blockId="control_event_source_id" block="%id" blockGap=8
|
//% weight=2 weight=19 blockId="control_event_source_id" block="%id" blockGap=8
|
||||||
|
//% shim=TD_ID
|
||||||
export function eventSourceId(id: EventBusSource): number {
|
export function eventSourceId(id: EventBusSource): number {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -15,6 +16,7 @@ namespace control {
|
|||||||
* Returns the value of a C++ runtime constant
|
* Returns the value of a C++ runtime constant
|
||||||
*/
|
*/
|
||||||
//% weight=1 weight=19 blockId="control_event_value_id" block="%id"
|
//% weight=1 weight=19 blockId="control_event_value_id" block="%id"
|
||||||
|
//% shim=TD_ID
|
||||||
export function eventValueId(id: EventBusValue): number {
|
export function eventValueId(id: EventBusValue): number {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -42,6 +44,5 @@ namespace control {
|
|||||||
* Display warning in the simulator.
|
* Display warning in the simulator.
|
||||||
*/
|
*/
|
||||||
//% shim=pxtrt::runtimeWarning
|
//% shim=pxtrt::runtimeWarning
|
||||||
export function runtimeWarning(message: string) {
|
export function runtimeWarning(message: string) { }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -166,6 +166,7 @@ namespace Array_ {
|
|||||||
int removeElement(RefCollection *c, uint32_t x) { return c->removeElement(x); }
|
int removeElement(RefCollection *c, uint32_t x) { return c->removeElement(x); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Import some stuff directly
|
// Import some stuff directly
|
||||||
namespace pxt {
|
namespace pxt {
|
||||||
//%
|
//%
|
||||||
@ -181,10 +182,12 @@ namespace pxt {
|
|||||||
//%
|
//%
|
||||||
Action mkAction(int reflen, int totallen, int startptr);
|
Action mkAction(int reflen, int totallen, int startptr);
|
||||||
//%
|
//%
|
||||||
RefRecord* mkRecord(int reflen, int totallen);
|
|
||||||
//%
|
|
||||||
RefRecord* mkClassInstance(int offset);
|
RefRecord* mkClassInstance(int offset);
|
||||||
//%
|
//%
|
||||||
|
void RefRecord_destroy(RefRecord *r);
|
||||||
|
//%
|
||||||
|
void RefRecord_print(RefRecord *r);
|
||||||
|
//%
|
||||||
void debugMemLeaks();
|
void debugMemLeaks();
|
||||||
//%
|
//%
|
||||||
int incr(uint32_t e);
|
int incr(uint32_t e);
|
||||||
@ -308,6 +311,72 @@ namespace pxtrt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//%
|
||||||
|
RefMap *mkMap() {
|
||||||
|
return new RefMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
//%
|
||||||
|
uint32_t mapGet(RefMap *map, uint32_t key) {
|
||||||
|
int i = map->findIdx(key);
|
||||||
|
if (i < 0) {
|
||||||
|
map->unref();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint32_t r = map->data[i].val;
|
||||||
|
map->unref();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
//%
|
||||||
|
uint32_t mapGetRef(RefMap *map, uint32_t key) {
|
||||||
|
int i = map->findIdx(key);
|
||||||
|
if (i < 0) {
|
||||||
|
map->unref();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint32_t r = incr(map->data[i].val);
|
||||||
|
map->unref();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
//%
|
||||||
|
void mapSet(RefMap *map, uint32_t key, uint32_t val) {
|
||||||
|
int i = map->findIdx(key);
|
||||||
|
if (i < 0) {
|
||||||
|
map->data.push_back({
|
||||||
|
key << 1,
|
||||||
|
val
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (map->data[i].key & 1) {
|
||||||
|
decr(map->data[i].val);
|
||||||
|
map->data[i].key = key << 1;
|
||||||
|
}
|
||||||
|
map->data[i].val = val;
|
||||||
|
}
|
||||||
|
map->unref();
|
||||||
|
}
|
||||||
|
|
||||||
|
//%
|
||||||
|
void mapSetRef(RefMap *map, uint32_t key, uint32_t val) {
|
||||||
|
int i = map->findIdx(key);
|
||||||
|
if (i < 0) {
|
||||||
|
map->data.push_back({
|
||||||
|
(key << 1) | 1,
|
||||||
|
val
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (map->data[i].key & 1) {
|
||||||
|
decr(map->data[i].val);
|
||||||
|
} else {
|
||||||
|
map->data[i].key = (key << 1) | 1;
|
||||||
|
}
|
||||||
|
map->data[i].val = val;
|
||||||
|
}
|
||||||
|
map->unref();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Debugger
|
// Debugger
|
||||||
//
|
//
|
||||||
|
@ -135,7 +135,7 @@ namespace music {
|
|||||||
*/
|
*/
|
||||||
//% help=music/play-tone weight=90
|
//% help=music/play-tone weight=90
|
||||||
//% blockId=device_play_note block="play|tone %note=device_note|for %duration=device_beat" icon="\uf025" blockGap=8
|
//% blockId=device_play_note block="play|tone %note=device_note|for %duration=device_beat" icon="\uf025" blockGap=8
|
||||||
//% parts="speaker"
|
//% parts="headphone"
|
||||||
export function playTone(frequency: number, ms: number): void {
|
export function playTone(frequency: number, ms: number): void {
|
||||||
pins.analogSetPitchPin(AnalogPin.P0);
|
pins.analogSetPitchPin(AnalogPin.P0);
|
||||||
pins.analogPitch(frequency, ms);
|
pins.analogPitch(frequency, ms);
|
||||||
@ -147,7 +147,7 @@ namespace music {
|
|||||||
*/
|
*/
|
||||||
//% help=music/ring-tone weight=80
|
//% help=music/ring-tone weight=80
|
||||||
//% blockId=device_ring block="ring tone (Hz)|%note=device_note" icon="\uf025" blockGap=8
|
//% blockId=device_ring block="ring tone (Hz)|%note=device_note" icon="\uf025" blockGap=8
|
||||||
//% parts="speaker"
|
//% parts="headphone"
|
||||||
export function ringTone(frequency: number): void {
|
export function ringTone(frequency: number): void {
|
||||||
pins.analogSetPitchPin(AnalogPin.P0);
|
pins.analogSetPitchPin(AnalogPin.P0);
|
||||||
pins.analogPitch(frequency, 0);
|
pins.analogPitch(frequency, 0);
|
||||||
@ -159,7 +159,7 @@ namespace music {
|
|||||||
*/
|
*/
|
||||||
//% help=music/rest weight=79
|
//% help=music/rest weight=79
|
||||||
//% blockId=device_rest block="rest(ms)|%duration=device_beat"
|
//% blockId=device_rest block="rest(ms)|%duration=device_beat"
|
||||||
//% parts="speaker"
|
//% parts="headphone"
|
||||||
export function rest(ms: number): void {
|
export function rest(ms: number): void {
|
||||||
playTone(0, ms);
|
playTone(0, ms);
|
||||||
}
|
}
|
||||||
@ -171,7 +171,6 @@ namespace music {
|
|||||||
*/
|
*/
|
||||||
//% weight=50 help=music/note-frequency
|
//% weight=50 help=music/note-frequency
|
||||||
//% blockId=device_note block="%note"
|
//% blockId=device_note block="%note"
|
||||||
//% parts="speaker"
|
|
||||||
//% shim=TD_ID
|
//% shim=TD_ID
|
||||||
export function noteFrequency(name: Note): number {
|
export function noteFrequency(name: Note): number {
|
||||||
return name;
|
return name;
|
||||||
@ -186,7 +185,6 @@ namespace music {
|
|||||||
*/
|
*/
|
||||||
//% help=music/beat weight=49
|
//% help=music/beat weight=49
|
||||||
//% blockId=device_beat block="%fraction|beat"
|
//% blockId=device_beat block="%fraction|beat"
|
||||||
//% parts="speaker"
|
|
||||||
export function beat(fraction?: BeatFraction): number {
|
export function beat(fraction?: BeatFraction): number {
|
||||||
init();
|
init();
|
||||||
if (fraction == null) fraction = BeatFraction.Whole;
|
if (fraction == null) fraction = BeatFraction.Whole;
|
||||||
@ -203,7 +201,6 @@ namespace music {
|
|||||||
*/
|
*/
|
||||||
//% help=music/tempo weight=40
|
//% help=music/tempo weight=40
|
||||||
//% blockId=device_tempo block="tempo (bpm)" blockGap=8
|
//% blockId=device_tempo block="tempo (bpm)" blockGap=8
|
||||||
//% parts="speaker"
|
|
||||||
export function tempo(): number {
|
export function tempo(): number {
|
||||||
init();
|
init();
|
||||||
return beatsPerMinute;
|
return beatsPerMinute;
|
||||||
@ -215,7 +212,6 @@ namespace music {
|
|||||||
*/
|
*/
|
||||||
//% help=music/change-tempo weight=39
|
//% help=music/change-tempo weight=39
|
||||||
//% blockId=device_change_tempo block="change tempo by (bpm)|%value" blockGap=8
|
//% blockId=device_change_tempo block="change tempo by (bpm)|%value" blockGap=8
|
||||||
//% parts="speaker"
|
|
||||||
export function changeTempoBy(bpm: number): void {
|
export function changeTempoBy(bpm: number): void {
|
||||||
init();
|
init();
|
||||||
setTempo(beatsPerMinute + bpm);
|
setTempo(beatsPerMinute + bpm);
|
||||||
@ -227,7 +223,6 @@ namespace music {
|
|||||||
*/
|
*/
|
||||||
//% help=music/set-tempo weight=38
|
//% help=music/set-tempo weight=38
|
||||||
//% blockId=device_set_tempo block="set tempo to (bpm)|%value"
|
//% blockId=device_set_tempo block="set tempo to (bpm)|%value"
|
||||||
//% parts="speaker"
|
|
||||||
export function setTempo(bpm: number): void {
|
export function setTempo(bpm: number): void {
|
||||||
init();
|
init();
|
||||||
if (bpm > 0) {
|
if (bpm > 0) {
|
||||||
|
1
libs/microbit/parts/headphone.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="142" height="180" viewBox="0 0 142 180"><rect ry=".3" rx="1" y="58.615" x="-8.878" height="23.571" width="17.143" transform="rotate(-45)" fill="#b3b3b3"/><rect ry=".3" rx="1" y="32.043" x="-8.878" height="23.571" width="17.143" transform="rotate(-45)" fill="#b3b3b3"/><path d="M.346 7.296c-.394.39-.31 4.797-.18 4.898l13.404 10.18c.117.12.337 4.76.73 4.368l5.506-5.56.01.01 6.51-6.444c.39-.392-4.25-.614-4.366-.73L11.777.612c-.1-.132-4.51-.215-4.898.18L4.087 3.636l-.01-.01-3.73 3.67z" fill="#b3b3b3"/><rect ry="6.85" rx="4.571" y="84.758" x="-20.128" height="75.571" width="39.643" transform="rotate(-45)"/><rect ry=".374" rx="1.038" y="29.442" x="-8.925" height="2.228" width="17.238" transform="rotate(-45)" fill="#fff"/><rect ry=".374" rx="1.038" y="55.939" x="-8.925" height="2.228" width="17.238" transform="rotate(-45)" fill="#fff"/><rect ry=".374" rx="1.038" y="82.392" x="-8.925" height="2.228" width="17.238" transform="rotate(-45)" fill="#fff"/><rect ry="2.317" rx="2.183" y="158.876" x="-9.774" height="25.568" width="18.935" transform="rotate(-45)"/><path d="M128.588 128.82s14.97 11.165 7.547 26.35c-8.426 17.24-25.57 20.653-25.57 20.653" fill="none" stroke="#000" stroke-width="6.6" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
After Width: | Height: | Size: 1.3 KiB |
@ -29,6 +29,7 @@
|
|||||||
"buffer.cpp",
|
"buffer.cpp",
|
||||||
"pxtparts.json",
|
"pxtparts.json",
|
||||||
"parts/speaker.svg",
|
"parts/speaker.svg",
|
||||||
|
"parts/headphone.svg",
|
||||||
"_locales/fr/microbit-jsdoc-strings.json"
|
"_locales/fr/microbit-jsdoc-strings.json"
|
||||||
],
|
],
|
||||||
"public": true,
|
"public": true,
|
||||||
|
@ -1,78 +1,148 @@
|
|||||||
{
|
{
|
||||||
"ledmatrix": {
|
"buttonpair": {
|
||||||
"visual": "ledmatrix",
|
"simulationBehavior": "buttonpair",
|
||||||
"breadboardColumnsNeeded": 8,
|
"visual": {
|
||||||
"breadboardStartRow": "h",
|
"builtIn": "buttonpair",
|
||||||
"pinAllocation": {
|
"width": 75,
|
||||||
"type": "auto",
|
"height": 45,
|
||||||
"gpioPinsNeeded": [5, 5]
|
"pinDistance": 15,
|
||||||
},
|
"pinLocations": [
|
||||||
"assemblyStep": 0,
|
{"x": 0, "y": 0},
|
||||||
"wires": [
|
{"x": 30, "y": 45},
|
||||||
{"start": ["breadboard", "j", 0], "end": ["GPIO", 5], "color": "purple", "assemblyStep": 1},
|
{"x": 45, "y": 0},
|
||||||
{"start": ["breadboard", "j", 1], "end": ["GPIO", 6], "color": "purple", "assemblyStep": 1},
|
{"x": 75, "y": 45}
|
||||||
{"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": {
|
"numberOfPins": 4,
|
||||||
"visual": "buttonpair",
|
"pinDefinitions": [
|
||||||
"breadboardColumnsNeeded": 6,
|
{"target": "P14", "style": "male", "orientation": "-Z"},
|
||||||
"breadboardStartRow": "f",
|
{"target": "ground", "style": "male", "orientation": "-Z"},
|
||||||
"pinAllocation": {
|
{"target": "P15", "style": "male", "orientation": "-Z"},
|
||||||
"type": "predefined",
|
{"target": "ground", "style": "male", "orientation": "-Z"}
|
||||||
"pins": ["P13", "P12"]
|
],
|
||||||
|
"instantiation": {
|
||||||
|
"kind": "singleton"
|
||||||
},
|
},
|
||||||
"assemblyStep": 0,
|
"assembly": [
|
||||||
"wires": [
|
{"part": true},
|
||||||
{"start": ["breadboard", "j", 0], "end": ["GPIO", 0], "color": "yellow", "assemblyStep": 1},
|
{"pinIndices": [0, 1]},
|
||||||
{"start": ["breadboard", "a", 2], "end": "ground", "color": "blue", "assemblyStep": 1},
|
{"pinIndices": [2, 3]}
|
||||||
{"start": ["breadboard", "j", 3], "end": ["GPIO", 1], "color": "orange", "assemblyStep": 2},
|
|
||||||
{"start": ["breadboard", "a", 5], "end": "ground", "color": "blue", "assemblyStep": 2}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"neopixel": {
|
"neopixel": {
|
||||||
"visual": "neopixel",
|
"simulationBehavior": "neopixel",
|
||||||
"breadboardColumnsNeeded": 5,
|
"visual": {
|
||||||
"breadboardStartRow": "h",
|
"builtIn": "neopixel",
|
||||||
"pinAllocation": {
|
"width": 58,
|
||||||
"type": "factoryfunction",
|
"height": 113,
|
||||||
"functionName": "neopixel.create",
|
"pinDistance": 9,
|
||||||
"pinArgPositions": [0],
|
"pinLocations": [
|
||||||
"otherArgPositions": [1]
|
{"x": 10, "y": 0},
|
||||||
|
{"x": 19, "y": 0},
|
||||||
|
{"x": 28, "y": 0}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"assemblyStep": 0,
|
"numberOfPins": 3,
|
||||||
"wires": [
|
"pinDefinitions": [
|
||||||
{"start": ["breadboard", "j", 1], "end": "ground", "color": "blue", "assemblyStep": 1},
|
{"target": {"pinInstantiationIdx": 0}, "style": "solder", "orientation": "+Z"},
|
||||||
{"start": ["breadboard", "j", 2], "end": "threeVolt", "color": "red", "assemblyStep": 2},
|
{"target": "threeVolt", "style": "solder", "orientation": "+Z"},
|
||||||
{"start": ["breadboard", "j", 3], "end": ["GPIO", 0], "color": "green", "assemblyStep": 2}
|
{"target": "ground", "style": "solder", "orientation": "+Z"}
|
||||||
|
],
|
||||||
|
"instantiation": {
|
||||||
|
"kind": "function",
|
||||||
|
"fullyQualifiedName": "neopixel.create",
|
||||||
|
"argumentRoles": [
|
||||||
|
{"pinInstantiationIdx": 0, "partParameter": "pin"},
|
||||||
|
{"partParameter": "mode"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"assembly": [
|
||||||
|
{"part": true, "pinIndices": [2]},
|
||||||
|
{"pinIndices": [0, 1]}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ledmatrix": {
|
||||||
|
"visual": {
|
||||||
|
"builtIn": "ledmatrix",
|
||||||
|
"width": 105,
|
||||||
|
"height": 105,
|
||||||
|
"pinDistance": 15,
|
||||||
|
"pinLocations": [
|
||||||
|
{"x": 0, "y": 0},
|
||||||
|
{"x": 15, "y": 0},
|
||||||
|
{"x": 30, "y": 0},
|
||||||
|
{"x": 45, "y": 0},
|
||||||
|
{"x": 105, "y": 105},
|
||||||
|
{"x": 0, "y": 105},
|
||||||
|
{"x": 15, "y": 105},
|
||||||
|
{"x": 30, "y": 105},
|
||||||
|
{"x": 45, "y": 105},
|
||||||
|
{"x": 60, "y": 0}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"simulationBehavior": "ledmatrix",
|
||||||
|
"numberOfPins": 10,
|
||||||
|
"instantiation": {"kind": "singleton"},
|
||||||
|
"pinDefinitions": [
|
||||||
|
{"target": "P6", "style": "male", "orientation": "-Z", "colorGroup": 0},
|
||||||
|
{"target": "P7", "style": "male", "orientation": "-Z", "colorGroup": 0},
|
||||||
|
{"target": "P8", "style": "male", "orientation": "-Z", "colorGroup": 0},
|
||||||
|
{"target": "P9", "style": "male", "orientation": "-Z", "colorGroup": 0},
|
||||||
|
{"target": "P10", "style": "male", "orientation": "-Z", "colorGroup": 0},
|
||||||
|
{"target": "P12", "style": "male", "orientation": "-Z", "colorGroup": 1},
|
||||||
|
{"target": "P13", "style": "male", "orientation": "-Z", "colorGroup": 1},
|
||||||
|
{"target": "P16", "style": "male", "orientation": "-Z", "colorGroup": 1},
|
||||||
|
{"target": "P19", "style": "male", "orientation": "-Z", "colorGroup": 1},
|
||||||
|
{"target": "P20", "style": "male", "orientation": "-Z", "colorGroup": 1}
|
||||||
|
],
|
||||||
|
"assembly": [
|
||||||
|
{"part": true},
|
||||||
|
{"pinIndices": [0, 1, 2, 3, 4]},
|
||||||
|
{"pinIndices": [5, 6, 7, 8, 9]}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"headphone": {
|
||||||
|
"numberOfPins": 2,
|
||||||
|
"visual": {
|
||||||
|
"image": "parts/headphone.svg",
|
||||||
|
"width": 142,
|
||||||
|
"height": 180,
|
||||||
|
"pinDistance": 20,
|
||||||
|
"pinLocations": [
|
||||||
|
{"x": 17, "y": 11},
|
||||||
|
{"x": 55, "y": 50}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"pinDefinitions": [
|
||||||
|
{"target": "P0", "style": "croc", "orientation": "Y"},
|
||||||
|
{"target": "ground", "style": "croc", "orientation": "Y"}
|
||||||
|
],
|
||||||
|
"instantiation": {"kind": "singleton"},
|
||||||
|
"assembly": [
|
||||||
|
{"part": true, "pinIndices": [0]},
|
||||||
|
{"pinIndices": [1]}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"speaker": {
|
"speaker": {
|
||||||
|
"numberOfPins": 2,
|
||||||
"visual": {
|
"visual": {
|
||||||
"image": "/parts/speaker.svg",
|
"image": "parts/speaker.svg",
|
||||||
"width": 500,
|
"width": 500,
|
||||||
"height": 500,
|
"height": 500,
|
||||||
"firstPin": [180, 135],
|
"pinDistance": 70,
|
||||||
"pinDist": 70,
|
"pinLocations": [
|
||||||
"extraColumnOffset": 1
|
{"x": 180, "y": 135},
|
||||||
|
{"x": 320, "y": 135}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"breadboardColumnsNeeded": 5,
|
"pinDefinitions": [
|
||||||
"breadboardStartRow": "f",
|
{"target": "P0", "style": "male", "orientation": "-Z"},
|
||||||
"pinAllocation": {
|
{"target": "ground", "style": "male", "orientation": "-Z"}
|
||||||
"type": "auto",
|
],
|
||||||
"gpioPinsNeeded": 1
|
"instantiation": {"kind": "singleton"},
|
||||||
},
|
"assembly": [
|
||||||
"assemblyStep": 0,
|
{"part": true, "pinIndices": [0]},
|
||||||
"wires": [
|
{"pinIndices": [1]}
|
||||||
{"start": ["breadboard", "j", 1], "end": ["GPIO", 0], "color": "#ff80fa", "assemblyStep": 1},
|
|
||||||
{"start": ["breadboard", "j", 3], "end": "ground", "color": "blue", "assemblyStep": 1}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pxt-microbit",
|
"name": "pxt-microbit",
|
||||||
"version": "0.3.78",
|
"version": "0.4.13",
|
||||||
"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.92"
|
"pxt-core": "0.4.17"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
186
pxtarget.json
@ -75,7 +75,9 @@
|
|||||||
},
|
},
|
||||||
"simulator": {
|
"simulator": {
|
||||||
"autoRun": true,
|
"autoRun": true,
|
||||||
|
"streams": true,
|
||||||
"aspectRatio": 1.22,
|
"aspectRatio": 1.22,
|
||||||
|
"parts": true,
|
||||||
"partsAspectRatio": 0.69,
|
"partsAspectRatio": 0.69,
|
||||||
"builtinParts": {
|
"builtinParts": {
|
||||||
"accelerometer": true,
|
"accelerometer": true,
|
||||||
@ -85,13 +87,102 @@
|
|||||||
"bluetooth": true,
|
"bluetooth": true,
|
||||||
"thermometer": true,
|
"thermometer": true,
|
||||||
"compass": true
|
"compass": true
|
||||||
|
},
|
||||||
|
"boardDefinition": {
|
||||||
|
"visual": "microbit",
|
||||||
|
"gpioPinBlocks": [
|
||||||
|
[
|
||||||
|
"P0"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"P1"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"P2"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"P3"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"P4",
|
||||||
|
"P5",
|
||||||
|
"P6",
|
||||||
|
"P7"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"P8",
|
||||||
|
"P9",
|
||||||
|
"P10",
|
||||||
|
"P11",
|
||||||
|
"P12"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"P16"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"gpioPinMap": {
|
||||||
|
"P0": "P0",
|
||||||
|
"P1": "P1",
|
||||||
|
"P2": "P2",
|
||||||
|
"P3": "P3",
|
||||||
|
"P4": "P4",
|
||||||
|
"P5": "P5",
|
||||||
|
"P6": "P6",
|
||||||
|
"P7": "P7",
|
||||||
|
"P8": "P8",
|
||||||
|
"P9": "P9",
|
||||||
|
"P10": "P10",
|
||||||
|
"P11": "P11",
|
||||||
|
"P12": "P12",
|
||||||
|
"P13": "P13",
|
||||||
|
"P14": "P14",
|
||||||
|
"P15": "P15",
|
||||||
|
"P16": "P16",
|
||||||
|
"P19": "P19",
|
||||||
|
"P20": "P20"
|
||||||
|
},
|
||||||
|
"spiPins": {
|
||||||
|
"MOSI": "P15",
|
||||||
|
"MISO": "P14",
|
||||||
|
"SCK": "P13"
|
||||||
|
},
|
||||||
|
"i2cPins": {
|
||||||
|
"SDA": "P20",
|
||||||
|
"SCL": "P19"
|
||||||
|
},
|
||||||
|
"analogInPins": [
|
||||||
|
"P0",
|
||||||
|
"P1",
|
||||||
|
"P2",
|
||||||
|
"P3",
|
||||||
|
"P10"
|
||||||
|
],
|
||||||
|
"groundPins": [
|
||||||
|
"GND"
|
||||||
|
],
|
||||||
|
"threeVoltPins": [
|
||||||
|
"+3v3"
|
||||||
|
],
|
||||||
|
"attachPowerOnRight": true,
|
||||||
|
"onboardComponents": [
|
||||||
|
"buttonpair",
|
||||||
|
"ledmatrix",
|
||||||
|
"speaker"
|
||||||
|
],
|
||||||
|
"useCrocClips": true,
|
||||||
|
"marginWhenBreadboarding": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
80,
|
||||||
|
0
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"compileService": {
|
"compileService": {
|
||||||
"yottaTarget": "bbc-microbit-classic-gcc",
|
"yottaTarget": "bbc-microbit-classic-gcc",
|
||||||
"yottaCorePackage": "pxt-microbit-core",
|
"yottaCorePackage": "pxt-microbit-core",
|
||||||
"githubCorePackage": "microsoft/pxt-microbit-core",
|
"githubCorePackage": "microsoft/pxt-microbit-core",
|
||||||
"gittag": "v0.4.2",
|
"gittag": "v0.5.0",
|
||||||
"serviceId": "ws"
|
"serviceId": "ws"
|
||||||
},
|
},
|
||||||
"serial": {
|
"serial": {
|
||||||
@ -113,6 +204,34 @@
|
|||||||
"embedUrl": "https://codethemicrobit.com/",
|
"embedUrl": "https://codethemicrobit.com/",
|
||||||
"privacyUrl": "https://go.microsoft.com/fwlink/?LinkId=521839",
|
"privacyUrl": "https://go.microsoft.com/fwlink/?LinkId=521839",
|
||||||
"termsOfUseUrl": "https://go.microsoft.com/fwlink/?LinkID=206977",
|
"termsOfUseUrl": "https://go.microsoft.com/fwlink/?LinkID=206977",
|
||||||
|
"githubUrl": "https://github.com/Microsoft/pxt-microbit",
|
||||||
|
"browserSupport": [
|
||||||
|
{
|
||||||
|
"name": "unsupported",
|
||||||
|
"os": "*",
|
||||||
|
"path": "/browsers"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "unsupported",
|
||||||
|
"os": "mac",
|
||||||
|
"path": "/browsers/mac"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "unsupported",
|
||||||
|
"os": "linux",
|
||||||
|
"path": "browsers/linux"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "unsupported",
|
||||||
|
"os": "rpi",
|
||||||
|
"path": "/raspberry-pi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "unsupported",
|
||||||
|
"os": "windows",
|
||||||
|
"path": "/browsers/windows"
|
||||||
|
}
|
||||||
|
],
|
||||||
"boardName": "BBC micro:bit",
|
"boardName": "BBC micro:bit",
|
||||||
"docMenu": [
|
"docMenu": [
|
||||||
{
|
{
|
||||||
@ -140,7 +259,70 @@
|
|||||||
"path": "/device"
|
"path": "/device"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sideDoc": "getting-started"
|
"sideDoc": "getting-started",
|
||||||
|
"usbDocs": "/device/usb",
|
||||||
|
"usbHelp": [
|
||||||
|
{
|
||||||
|
"name": "connection",
|
||||||
|
"os": "*",
|
||||||
|
"browser": "*",
|
||||||
|
"path": "/static/mb/device/usb-generic.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "connection",
|
||||||
|
"os": "mac",
|
||||||
|
"browser": "*",
|
||||||
|
"path": "/static/mb/device/usb-mac.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "save",
|
||||||
|
"os": "windows",
|
||||||
|
"browser": "firefox",
|
||||||
|
"path": "/static/mb/device/usb-windows-firefox-1.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "save",
|
||||||
|
"os": "mac",
|
||||||
|
"browser": "firefox",
|
||||||
|
"path": "/static/mb/device/usb-osx-firefox-1.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "save",
|
||||||
|
"os": "mac",
|
||||||
|
"browser": "chrome",
|
||||||
|
"path": "/static/mb/device/usb-osx-chrome.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "save",
|
||||||
|
"os": "windows",
|
||||||
|
"browser": "edge",
|
||||||
|
"path": "/static/mb/device/usb-windows-edge-1.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "save",
|
||||||
|
"os": "windows",
|
||||||
|
"browser": "ie",
|
||||||
|
"path": "/static/mb/device/usb-windows-ie11-1.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "save",
|
||||||
|
"os": "windows",
|
||||||
|
"browser": "chrome",
|
||||||
|
"path": "/static/mb/device/usb-windows-chrome.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "copy",
|
||||||
|
"os": "mac",
|
||||||
|
"browser": "*",
|
||||||
|
"path": "/static/mb/device/usb-osx-dnd.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "copy",
|
||||||
|
"os": "windows",
|
||||||
|
"browser": "*",
|
||||||
|
"path": "/static/mb/device/usb-windows-sendto.jpg"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"analytics": {
|
"analytics": {
|
||||||
"userVoiceApiKey": "WEkkIGaj1WtJnSUF59iwaA",
|
"userVoiceApiKey": "WEkkIGaj1WtJnSUF59iwaA",
|
||||||
|
556
sim/allocator.ts
@ -1,556 +0,0 @@
|
|||||||
|
|
||||||
namespace pxsim {
|
|
||||||
export interface AllocatorOpts {
|
|
||||||
boardDef: BoardDefinition,
|
|
||||||
cmpDefs: Map<PartDefinition>,
|
|
||||||
fnArgs: any,
|
|
||||||
getBBCoord: (loc: BBRowCol) => visuals.Coord,
|
|
||||||
cmpList: string[]
|
|
||||||
};
|
|
||||||
export interface AllocatorResult {
|
|
||||||
powerWires: WireInst[],
|
|
||||||
components: CmpAndWireInst[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CmpAndWireInst {
|
|
||||||
component: CmpInst,
|
|
||||||
wires: WireInst[]
|
|
||||||
}
|
|
||||||
export interface CmpInst {
|
|
||||||
name: string,
|
|
||||||
breadboardStartColumn: number,
|
|
||||||
breadboardStartRow: string,
|
|
||||||
assemblyStep: number,
|
|
||||||
visual: string | PartVisualDefinition,
|
|
||||||
microbitPins: string[],
|
|
||||||
otherArgs?: string[],
|
|
||||||
}
|
|
||||||
export interface WireInst {
|
|
||||||
start: Loc,
|
|
||||||
end: Loc,
|
|
||||||
color: string,
|
|
||||||
assemblyStep: number
|
|
||||||
};
|
|
||||||
interface PartialCmpAlloc {
|
|
||||||
name: string,
|
|
||||||
def: PartDefinition,
|
|
||||||
pinsAssigned: string[],
|
|
||||||
pinsNeeded: number | number[],
|
|
||||||
breadboardColumnsNeeded: number,
|
|
||||||
otherArgs?: string[],
|
|
||||||
}
|
|
||||||
|
|
||||||
interface AllocLocOpts {
|
|
||||||
nearestBBPin?: BBRowCol,
|
|
||||||
startColumn?: number,
|
|
||||||
cmpGPIOPins?: string[],
|
|
||||||
};
|
|
||||||
interface AllocWireOpts {
|
|
||||||
startColumn: number,
|
|
||||||
cmpGPIOPins: string[],
|
|
||||||
}
|
|
||||||
interface AllocBlock {
|
|
||||||
cmpIdx: number,
|
|
||||||
cmpBlkIdx: number,
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
function readPin(arg: string): string {
|
|
||||||
U.assert(!!arg, "Invalid pin: " + arg);
|
|
||||||
let pin = arg.split("DigitalPin.")[1];
|
|
||||||
return pin;
|
|
||||||
}
|
|
||||||
function mkReverseMap(map: {[key: string]: string}) {
|
|
||||||
let origKeys: string[] = [];
|
|
||||||
let origVals: string[] = [];
|
|
||||||
for (let key in map) {
|
|
||||||
origKeys.push(key);
|
|
||||||
origVals.push(map[key]);
|
|
||||||
}
|
|
||||||
let newMap: {[key: string]: string} = {};
|
|
||||||
for (let i = 0; i < origKeys.length; i++) {
|
|
||||||
let newKey = origVals[i];
|
|
||||||
let newVal = origKeys[i];
|
|
||||||
newMap[newKey] = newVal;
|
|
||||||
}
|
|
||||||
return newMap;
|
|
||||||
}
|
|
||||||
class Allocator {
|
|
||||||
private opts: AllocatorOpts;
|
|
||||||
private availablePowerPins = {
|
|
||||||
top: {
|
|
||||||
threeVolt: mkRange(26, 51).map(n => <BBRowCol>["+", `${n}`]),
|
|
||||||
ground: mkRange(26, 51).map(n => <BBRowCol>["-", `${n}`]),
|
|
||||||
},
|
|
||||||
bottom: {
|
|
||||||
threeVolt: mkRange(1, 26).map(n => <BBRowCol>["+", `${n}`]),
|
|
||||||
ground: mkRange(1, 26).map(n => <BBRowCol>["-", `${n}`]),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
private powerUsage: PowerUsage;
|
|
||||||
|
|
||||||
constructor(opts: AllocatorOpts) {
|
|
||||||
this.opts = opts;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 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]
|
|
||||||
].map(loc => {
|
|
||||||
return this.opts.getBBCoord(loc);
|
|
||||||
});
|
|
||||||
if (!firstTopAndBot[0] || !firstTopAndBot[1]) {
|
|
||||||
console.debug(`No more available "${location}" locations!`);
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
let nearTop = visuals.findClosestCoordIdx(nearestCoord, firstTopAndBot) == 0;
|
|
||||||
let barPins: BBRowCol[];
|
|
||||||
if (nearTop) {
|
|
||||||
if (location === "ground") {
|
|
||||||
barPins = this.availablePowerPins.top.ground;
|
|
||||||
} else if (location === "threeVolt") {
|
|
||||||
barPins = this.availablePowerPins.top.threeVolt;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (location === "ground") {
|
|
||||||
barPins = this.availablePowerPins.bottom.ground;
|
|
||||||
} else if (location === "threeVolt") {
|
|
||||||
barPins = this.availablePowerPins.bottom.threeVolt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let pinCoords = barPins.map(rowCol => {
|
|
||||||
return this.opts.getBBCoord(rowCol);
|
|
||||||
});
|
|
||||||
let closestPinIdx = visuals.findClosestCoordIdx(nearestCoord, pinCoords);
|
|
||||||
let pin = barPins[closestPinIdx];
|
|
||||||
if (nearTop) {
|
|
||||||
this.availablePowerPins.top.ground.splice(closestPinIdx, 1);
|
|
||||||
this.availablePowerPins.top.threeVolt.splice(closestPinIdx, 1);
|
|
||||||
} else {
|
|
||||||
this.availablePowerPins.bottom.ground.splice(closestPinIdx, 1);
|
|
||||||
this.availablePowerPins.bottom.threeVolt.splice(closestPinIdx, 1);
|
|
||||||
}
|
|
||||||
return {type: "breadboard", rowCol: pin};
|
|
||||||
} else if (location[0] === "breadboard") {
|
|
||||||
U.assert(!!opts.startColumn);
|
|
||||||
let row = <string>location[1];
|
|
||||||
let col = (<number>location[2] + opts.startColumn).toString();
|
|
||||||
return {type: "breadboard", rowCol: [row, col]}
|
|
||||||
} else if (location[0] === "GPIO") {
|
|
||||||
U.assert(!!opts.cmpGPIOPins);
|
|
||||||
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 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"];
|
|
||||||
let botRight: BBRowCol = ["-", "25"];
|
|
||||||
let top: BBRowCol, bot: BBRowCol;
|
|
||||||
if (this.opts.boardDef.attachPowerOnRight) {
|
|
||||||
top = topRight;
|
|
||||||
bot = botRight;
|
|
||||||
} else {
|
|
||||||
top = topLeft;
|
|
||||||
bot = botLeft;
|
|
||||||
}
|
|
||||||
const GROUND_COLOR = "blue";
|
|
||||||
const POWER_COLOR = "red";
|
|
||||||
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]; // non-power end
|
|
||||||
let l = this.allocateLocation(ends[idx], {
|
|
||||||
nearestBBPin: locInst.rowCol,
|
|
||||||
startColumn: opts.startColumn,
|
|
||||||
cmpGPIOPins: opts.cmpGPIOPins,
|
|
||||||
});
|
|
||||||
return l;
|
|
||||||
});
|
|
||||||
return {start: endInsts[0], end: endInsts[1], color: wireDef.color, assemblyStep: wireDef.assemblyStep};
|
|
||||||
}
|
|
||||||
private allocatePartialCmps(): PartialCmpAlloc[] {
|
|
||||||
let cmpNmAndDefs = this.opts.cmpList.map(cmpName => <[string, PartDefinition]>[cmpName, this.opts.cmpDefs[cmpName]]).filter(d => !!d[1]);
|
|
||||||
let cmpNmsList = cmpNmAndDefs.map(p => p[0]);
|
|
||||||
let cmpDefsList = cmpNmAndDefs.map(p => p[1]);
|
|
||||||
let partialCmps: PartialCmpAlloc[] = [];
|
|
||||||
cmpDefsList.forEach((def, idx) => {
|
|
||||||
let nm = cmpNmsList[idx];
|
|
||||||
if (def.pinAllocation.type === "predefined") {
|
|
||||||
let mbPins = (<PredefinedPinAlloc>def.pinAllocation).pins;
|
|
||||||
let pinsAssigned = mbPins.map(p => this.opts.boardDef.gpioPinMap[p]);
|
|
||||||
partialCmps.push({
|
|
||||||
name: nm,
|
|
||||||
def: def,
|
|
||||||
pinsAssigned: pinsAssigned,
|
|
||||||
pinsNeeded: 0,
|
|
||||||
breadboardColumnsNeeded: def.breadboardColumnsNeeded,
|
|
||||||
});
|
|
||||||
} else if (def.pinAllocation.type === "factoryfunction") {
|
|
||||||
let fnPinAlloc = (<FactoryFunctionPinAlloc>def.pinAllocation);
|
|
||||||
let fnNm = fnPinAlloc.functionName;
|
|
||||||
let fnsAndArgs = <string[]>this.opts.fnArgs[fnNm];
|
|
||||||
let success = false;
|
|
||||||
if (fnsAndArgs && fnsAndArgs.length) {
|
|
||||||
let pinArgPoses = fnPinAlloc.pinArgPositions;
|
|
||||||
let otherArgPoses = fnPinAlloc.otherArgPositions || [];
|
|
||||||
fnsAndArgs.forEach(fnArgsStr => {
|
|
||||||
let fnArgsSplit = fnArgsStr.split(",");
|
|
||||||
let pinArgs: string[] = [];
|
|
||||||
pinArgPoses.forEach(i => {
|
|
||||||
pinArgs.push(fnArgsSplit[i]);
|
|
||||||
});
|
|
||||||
let mbPins = pinArgs.map(arg => readPin(arg));
|
|
||||||
let otherArgs: string[] = [];
|
|
||||||
otherArgPoses.forEach(i => {
|
|
||||||
otherArgs.push(fnArgsSplit[i]);
|
|
||||||
});
|
|
||||||
let pinsAssigned = mbPins.map(p => this.opts.boardDef.gpioPinMap[p]);
|
|
||||||
partialCmps.push({
|
|
||||||
name: nm,
|
|
||||||
def: def,
|
|
||||||
pinsAssigned: pinsAssigned,
|
|
||||||
pinsNeeded: 0,
|
|
||||||
breadboardColumnsNeeded: def.breadboardColumnsNeeded,
|
|
||||||
otherArgs: otherArgs.length ? otherArgs : null,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// failed to find pin allocation from callsites
|
|
||||||
console.debug("Failed to read pin(s) from callsite for: " + fnNm);
|
|
||||||
let pinsNeeded = fnPinAlloc.pinArgPositions.length;
|
|
||||||
partialCmps.push({
|
|
||||||
name: nm,
|
|
||||||
def: def,
|
|
||||||
pinsAssigned: [],
|
|
||||||
pinsNeeded: pinsNeeded,
|
|
||||||
breadboardColumnsNeeded: def.breadboardColumnsNeeded,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (def.pinAllocation.type === "auto") {
|
|
||||||
let pinsNeeded = (<AutoPinAlloc>def.pinAllocation).gpioPinsNeeded;
|
|
||||||
partialCmps.push({
|
|
||||||
name: nm,
|
|
||||||
def: def,
|
|
||||||
pinsAssigned: [],
|
|
||||||
pinsNeeded: pinsNeeded,
|
|
||||||
breadboardColumnsNeeded: def.breadboardColumnsNeeded,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return partialCmps;
|
|
||||||
}
|
|
||||||
private allocateGPIOPins(partialCmps: PartialCmpAlloc[]): string[][] {
|
|
||||||
let availableGPIOBlocks = copyDoubleArray(this.opts.boardDef.gpioPinBlocks);
|
|
||||||
let sortAvailableGPIOBlocks = () => availableGPIOBlocks.sort((a, b) => a.length - b.length); //smallest blocks first
|
|
||||||
// determine blocks needed
|
|
||||||
let blockAssignments: AllocBlock[] = [];
|
|
||||||
let preassignedPins: string[] = [];
|
|
||||||
partialCmps.forEach((cmp, idx) => {
|
|
||||||
if (cmp.pinsAssigned && cmp.pinsAssigned.length) {
|
|
||||||
//already assigned
|
|
||||||
blockAssignments.push({cmpIdx: idx, cmpBlkIdx: 0, gpioNeeded: 0, gpioAssigned: cmp.pinsAssigned});
|
|
||||||
preassignedPins = preassignedPins.concat(cmp.pinsAssigned);
|
|
||||||
} else if (cmp.pinsNeeded) {
|
|
||||||
if (typeof cmp.pinsNeeded === "number") {
|
|
||||||
//individual pins
|
|
||||||
for (let i = 0; i < cmp.pinsNeeded; i++) {
|
|
||||||
blockAssignments.push(
|
|
||||||
{cmpIdx: idx, cmpBlkIdx: 0, gpioNeeded: 1, gpioAssigned: []});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//blocks of pins
|
|
||||||
let blocks = <number[]>cmp.pinsNeeded;
|
|
||||||
blocks.forEach((numNeeded, blkIdx) => {
|
|
||||||
blockAssignments.push(
|
|
||||||
{cmpIdx: idx, cmpBlkIdx: blkIdx, gpioNeeded: numNeeded, gpioAssigned: []});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// remove assigned blocks
|
|
||||||
availableGPIOBlocks.forEach(blks => {
|
|
||||||
for (let i = blks.length - 1; 0 <= i; i--) {
|
|
||||||
let pin = blks[i];
|
|
||||||
if (0 <= preassignedPins.indexOf(pin)) {
|
|
||||||
blks.splice(i, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// sort by size of blocks
|
|
||||||
let sortBlockAssignments = () => blockAssignments.sort((a, b) => b.gpioNeeded - a.gpioNeeded); //largest blocks first
|
|
||||||
// allocate each block
|
|
||||||
if (0 < blockAssignments.length && 0 < availableGPIOBlocks.length) {
|
|
||||||
do {
|
|
||||||
sortBlockAssignments();
|
|
||||||
sortAvailableGPIOBlocks();
|
|
||||||
let assignment = blockAssignments[0];
|
|
||||||
let smallestAvailableBlockThatFits: string[];
|
|
||||||
for (let j = 0; j < availableGPIOBlocks.length; j++) {
|
|
||||||
smallestAvailableBlockThatFits = availableGPIOBlocks[j];
|
|
||||||
if (assignment.gpioNeeded <= availableGPIOBlocks[j].length) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!smallestAvailableBlockThatFits || smallestAvailableBlockThatFits.length <= 0) {
|
|
||||||
break; // out of pins
|
|
||||||
}
|
|
||||||
while (0 < assignment.gpioNeeded && 0 < smallestAvailableBlockThatFits.length) {
|
|
||||||
assignment.gpioNeeded--;
|
|
||||||
let pin = smallestAvailableBlockThatFits[0];
|
|
||||||
smallestAvailableBlockThatFits.splice(0, 1);
|
|
||||||
assignment.gpioAssigned.push(pin);
|
|
||||||
}
|
|
||||||
sortBlockAssignments();
|
|
||||||
} while (0 < blockAssignments[0].gpioNeeded);
|
|
||||||
}
|
|
||||||
if (0 < blockAssignments.length && 0 < blockAssignments[0].gpioNeeded) {
|
|
||||||
console.debug("Not enough GPIO pins!");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
let cmpGPIOPinBlocks: string[][][] = partialCmps.map((def, cmpIdx) => {
|
|
||||||
if (!def)
|
|
||||||
return null;
|
|
||||||
let assignments = blockAssignments.filter(a => a.cmpIdx === cmpIdx);
|
|
||||||
let gpioPins: string[][] = [];
|
|
||||||
for (let i = 0; i < assignments.length; i++) {
|
|
||||||
let a = assignments[i];
|
|
||||||
let blk = gpioPins[a.cmpBlkIdx] || (gpioPins[a.cmpBlkIdx] = []);
|
|
||||||
a.gpioAssigned.forEach(p => blk.push(p));
|
|
||||||
}
|
|
||||||
return gpioPins;
|
|
||||||
});
|
|
||||||
let cmpGPIOPins = cmpGPIOPinBlocks.map(blks => blks.reduce((p, n) => p.concat(n), []));
|
|
||||||
return cmpGPIOPins;
|
|
||||||
}
|
|
||||||
private allocateColumns(partialCmps: PartialCmpAlloc[]): number[] {
|
|
||||||
let componentsCount = partialCmps.length;
|
|
||||||
let totalAvailableSpace = 30; //TODO allow multiple breadboards
|
|
||||||
let totalSpaceNeeded = partialCmps.map(d => d.breadboardColumnsNeeded).reduce((p, n) => p + n, 0);
|
|
||||||
let extraSpace = totalAvailableSpace - totalSpaceNeeded;
|
|
||||||
if (extraSpace <= 0) {
|
|
||||||
console.log("Not enough breadboard space!");
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
let padding = Math.floor(extraSpace / (componentsCount - 1 + 2));
|
|
||||||
let componentSpacing = padding; //Math.floor(extraSpace/(componentsCount-1));
|
|
||||||
let totalCmpPadding = extraSpace - componentSpacing * (componentsCount - 1);
|
|
||||||
let leftPadding = Math.floor(totalCmpPadding / 2);
|
|
||||||
let rightPadding = Math.ceil(totalCmpPadding / 2);
|
|
||||||
let nextAvailableCol = 1 + leftPadding;
|
|
||||||
let cmpStartCol = partialCmps.map(cmp => {
|
|
||||||
let col = nextAvailableCol;
|
|
||||||
nextAvailableCol += cmp.breadboardColumnsNeeded + componentSpacing;
|
|
||||||
return col;
|
|
||||||
});
|
|
||||||
return cmpStartCol;
|
|
||||||
}
|
|
||||||
private allocateComponent(partialCmp: PartialCmpAlloc, startColumn: number, microbitPins: string[]): CmpInst {
|
|
||||||
return {
|
|
||||||
name: partialCmp.name,
|
|
||||||
breadboardStartColumn: startColumn,
|
|
||||||
breadboardStartRow: partialCmp.def.breadboardStartRow,
|
|
||||||
assemblyStep: partialCmp.def.assemblyStep,
|
|
||||||
visual: partialCmp.def.visual,
|
|
||||||
microbitPins: microbitPins,
|
|
||||||
otherArgs: partialCmp.otherArgs,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public allocateAll(): AllocatorResult {
|
|
||||||
let cmpList = this.opts.cmpList;
|
|
||||||
let basicWires: WireInst[] = [];
|
|
||||||
let cmpsAndWires: CmpAndWireInst[] = [];
|
|
||||||
if (cmpList.length > 0) {
|
|
||||||
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]));
|
|
||||||
let cmpStartCol = this.allocateColumns(partialCmps);
|
|
||||||
let cmps = partialCmps.map((c, idx) => this.allocateComponent(c, cmpStartCol[idx], cmpMicrobitPins[idx]));
|
|
||||||
let wires = partialCmps.map((c, idx) => c.def.wires.map(d => this.allocateWire(d, {
|
|
||||||
cmpGPIOPins: cmpGPIOPins[idx],
|
|
||||||
startColumn: cmpStartCol[idx],
|
|
||||||
})));
|
|
||||||
cmpsAndWires = cmps.map((c, idx) => {
|
|
||||||
return {component: c, wires: wires[idx]}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
powerWires: basicWires,
|
|
||||||
components: cmpsAndWires
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function allocateDefinitions(opts: AllocatorOpts): AllocatorResult {
|
|
||||||
return new Allocator(opts).allocateAll();
|
|
||||||
}
|
|
||||||
}
|
|
132
sim/dalboard.ts
@ -1,12 +1,7 @@
|
|||||||
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
|
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
|
||||||
|
|
||||||
namespace pxsim {
|
namespace pxsim {
|
||||||
export class DalBoard extends BaseBoard {
|
export class DalBoard extends CoreBoard {
|
||||||
id: string;
|
|
||||||
|
|
||||||
// the bus
|
|
||||||
bus: EventBus;
|
|
||||||
|
|
||||||
// state & update logic for component services
|
// state & update logic for component services
|
||||||
ledMatrixState: LedMatrixState;
|
ledMatrixState: LedMatrixState;
|
||||||
edgeConnectorState: EdgeConnectorState;
|
edgeConnectorState: EdgeConnectorState;
|
||||||
@ -19,31 +14,58 @@ namespace pxsim {
|
|||||||
radioState: RadioState;
|
radioState: RadioState;
|
||||||
neopixelState: NeoPixelState;
|
neopixelState: NeoPixelState;
|
||||||
|
|
||||||
// updates
|
|
||||||
updateSubscribers: (() => void)[];
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
this.id = "b" + Math_.random(2147483647);
|
|
||||||
this.bus = new EventBus(runtime);
|
|
||||||
|
|
||||||
// components
|
// components
|
||||||
this.ledMatrixState = new LedMatrixState(runtime);
|
this.builtinParts["ledmatrix"] = this.ledMatrixState = new LedMatrixState(runtime);
|
||||||
this.buttonPairState = new ButtonPairState();
|
this.builtinParts["buttonpair"] = this.buttonPairState = new ButtonPairState({
|
||||||
this.edgeConnectorState = new EdgeConnectorState();
|
ID_BUTTON_A: DAL.MICROBIT_ID_BUTTON_A,
|
||||||
this.radioState = new RadioState(runtime);
|
ID_BUTTON_B: DAL.MICROBIT_ID_BUTTON_B,
|
||||||
this.accelerometerState = new AccelerometerState(runtime);
|
ID_BUTTON_AB: DAL.MICROBIT_ID_BUTTON_AB,
|
||||||
this.serialState = new SerialState();
|
BUTTON_EVT_UP: DAL.MICROBIT_BUTTON_EVT_UP,
|
||||||
this.thermometerState = new ThermometerState();
|
BUTTON_EVT_CLICK: DAL.MICROBIT_BUTTON_EVT_CLICK
|
||||||
this.lightSensorState = new LightSensorState();
|
});
|
||||||
this.compassState = new CompassState();
|
this.builtinParts["edgeconnector"] = this.edgeConnectorState = new EdgeConnectorState({
|
||||||
this.neopixelState = new NeoPixelState();
|
pins: [
|
||||||
|
DAL.MICROBIT_ID_IO_P0,
|
||||||
|
DAL.MICROBIT_ID_IO_P1,
|
||||||
|
DAL.MICROBIT_ID_IO_P2,
|
||||||
|
DAL.MICROBIT_ID_IO_P3,
|
||||||
|
DAL.MICROBIT_ID_IO_P4,
|
||||||
|
DAL.MICROBIT_ID_IO_P5,
|
||||||
|
DAL.MICROBIT_ID_IO_P6,
|
||||||
|
DAL.MICROBIT_ID_IO_P7,
|
||||||
|
DAL.MICROBIT_ID_IO_P8,
|
||||||
|
DAL.MICROBIT_ID_IO_P9,
|
||||||
|
DAL.MICROBIT_ID_IO_P10,
|
||||||
|
DAL.MICROBIT_ID_IO_P11,
|
||||||
|
DAL.MICROBIT_ID_IO_P12,
|
||||||
|
DAL.MICROBIT_ID_IO_P13,
|
||||||
|
DAL.MICROBIT_ID_IO_P14,
|
||||||
|
DAL.MICROBIT_ID_IO_P15,
|
||||||
|
DAL.MICROBIT_ID_IO_P16,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
DAL.MICROBIT_ID_IO_P19,
|
||||||
|
DAL.MICROBIT_ID_IO_P20
|
||||||
|
]
|
||||||
|
});
|
||||||
|
this.builtinParts["radio"] = this.radioState = new RadioState(runtime);
|
||||||
|
this.builtinParts["accelerometer"] = this.accelerometerState = new AccelerometerState(runtime);
|
||||||
|
this.builtinParts["serial"] = this.serialState = new SerialState();
|
||||||
|
this.builtinParts["thermometer"] = this.thermometerState = new ThermometerState();
|
||||||
|
this.builtinParts["lightsensor"] = this.lightSensorState = new LightSensorState();
|
||||||
|
this.builtinParts["compass"] = this.compassState = new CompassState();
|
||||||
|
this.builtinParts["neopixel"] = this.neopixelState = new NeoPixelState();
|
||||||
|
|
||||||
// updates
|
this.builtinVisuals["buttonpair"] = () => new visuals.ButtonPairView();
|
||||||
this.updateSubscribers = []
|
this.builtinVisuals["ledmatrix"] = () => new visuals.LedMatrixView();
|
||||||
this.updateView = () => {
|
this.builtinVisuals["neopixel"] = () => new visuals.NeoPixelView();
|
||||||
this.updateSubscribers.forEach(sub => sub());
|
|
||||||
}
|
this.builtinPartVisuals["buttonpair"] = (xy: visuals.Coord) => visuals.mkBtnSvg(xy);
|
||||||
|
this.builtinPartVisuals["ledmatrix"] = (xy: visuals.Coord) => visuals.mkLedMatrixSvg(xy, 8, 8);
|
||||||
|
this.builtinPartVisuals["neopixel"] = (xy: visuals.Coord) => visuals.mkNeoPixelPart(xy);
|
||||||
}
|
}
|
||||||
|
|
||||||
receiveMessage(msg: SimulatorMessage) {
|
receiveMessage(msg: SimulatorMessage) {
|
||||||
@ -65,31 +87,26 @@ namespace pxsim {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kill() {
|
|
||||||
super.kill();
|
|
||||||
AudioContextManager.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
initAsync(msg: SimulatorRunMessage): Promise<void> {
|
initAsync(msg: SimulatorRunMessage): Promise<void> {
|
||||||
super.initAsync(msg);
|
super.initAsync(msg);
|
||||||
|
|
||||||
let options = (msg.options || {}) as RuntimeOptions;
|
const options = (msg.options || {}) as RuntimeOptions;
|
||||||
|
|
||||||
let boardDef = CURRENT_BOARD; //TODO: read from pxt.json/pxttarget.json
|
const boardDef = msg.boardDefinition;
|
||||||
|
const cmpsList = msg.parts;
|
||||||
|
const cmpDefs = msg.partDefinitions || {};
|
||||||
|
const fnArgs = msg.fnArgs;
|
||||||
|
|
||||||
let cmpsList = msg.parts;
|
const opts : visuals.BoardHostOpts = {
|
||||||
let cmpDefs = msg.partDefinitions || {}; //TODO: read from pxt.json/pxttarget.json
|
|
||||||
let fnArgs = msg.fnArgs;
|
|
||||||
|
|
||||||
let viewHost = new visuals.BoardHost({
|
|
||||||
state: this,
|
state: this,
|
||||||
boardDef: boardDef,
|
boardDef: boardDef,
|
||||||
cmpsList: cmpsList,
|
partsList: cmpsList,
|
||||||
cmpDefs: cmpDefs,
|
partDefs: cmpDefs,
|
||||||
fnArgs: fnArgs,
|
fnArgs: fnArgs,
|
||||||
maxWidth: "100%",
|
maxWidth: "100%",
|
||||||
maxHeight: "100%",
|
maxHeight: "100%",
|
||||||
});
|
};
|
||||||
|
const viewHost = new visuals.BoardHost(pxsim.visuals.mkBoardView(opts), opts);
|
||||||
|
|
||||||
document.body.innerHTML = ""; // clear children
|
document.body.innerHTML = ""; // clear children
|
||||||
document.body.appendChild(viewHost.getView());
|
document.body.appendChild(viewHost.getView());
|
||||||
@ -97,4 +114,37 @@ namespace pxsim {
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function initRuntimeWithDalBoard() {
|
||||||
|
U.assert(!runtime.board);
|
||||||
|
let b = new DalBoard();
|
||||||
|
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) {
|
||||||
|
pxsim.initCurrentRuntime = initRuntimeWithDalBoard;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function board() {
|
||||||
|
return runtime.board as DalBoard;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,81 +0,0 @@
|
|||||||
/// <reference path="../node_modules/pxt-core/typings/bluebird/bluebird.d.ts"/>
|
|
||||||
/// <reference path="../node_modules/pxt-core/built/pxtparts.d.ts"/>
|
|
||||||
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
|
|
||||||
/// <reference path="../libs/microbit/dal.d.ts"/>
|
|
||||||
/// <reference path="./visuals/neopixel.ts"/>
|
|
||||||
|
|
||||||
namespace pxsim {
|
|
||||||
export const MICROBIT_DEF: BoardDefinition = {
|
|
||||||
visual: "microbit",
|
|
||||||
gpioPinBlocks: [
|
|
||||||
["P0"], ["P1"], ["P2"],
|
|
||||||
["P3"],
|
|
||||||
["P4", "P5", "P6", "P7"],
|
|
||||||
["P8", "P9", "P10", "P11", "P12"],
|
|
||||||
["P16"],
|
|
||||||
],
|
|
||||||
gpioPinMap: {
|
|
||||||
"P0": "P0",
|
|
||||||
"P1": "P1",
|
|
||||||
"P2": "P2",
|
|
||||||
"P3": "P3",
|
|
||||||
"P4": "P4",
|
|
||||||
"P5": "P5",
|
|
||||||
"P6": "P6",
|
|
||||||
"P7": "P7",
|
|
||||||
"P8": "P8",
|
|
||||||
"P9": "P9",
|
|
||||||
"P10": "P10",
|
|
||||||
"P11": "P11",
|
|
||||||
"P12": "P12",
|
|
||||||
"P13": "P13",
|
|
||||||
"P14": "P14",
|
|
||||||
"P15": "P15",
|
|
||||||
"P16": "P16",
|
|
||||||
"P19": "P19",
|
|
||||||
"P20": "P20",
|
|
||||||
},
|
|
||||||
spiPins: {
|
|
||||||
MOSI: "P15",
|
|
||||||
MISO: "P14",
|
|
||||||
SCK: "P13",
|
|
||||||
},
|
|
||||||
i2cPins: {
|
|
||||||
SDA: "P20",
|
|
||||||
SCL: "P19",
|
|
||||||
},
|
|
||||||
analogInPins: ["P0", "P1", "P2", "P3", "P10"],
|
|
||||||
groundPins: ["GND"],
|
|
||||||
threeVoltPins: ["+3v3"],
|
|
||||||
attachPowerOnRight: true,
|
|
||||||
onboardComponents: ["buttonpair", "ledmatrix", "speaker"],
|
|
||||||
useCrocClips: true,
|
|
||||||
marginWhenBreadboarding: [0, 0, 80, 0],
|
|
||||||
}
|
|
||||||
|
|
||||||
export const builtinComponentSimVisual: Map<() => visuals.IBoardComponent<any>> = {
|
|
||||||
"buttonpair": () => new visuals.ButtonPairView(),
|
|
||||||
"ledmatrix": () => new visuals.LedMatrixView(),
|
|
||||||
"neopixel": () => new visuals.NeoPixelView(),
|
|
||||||
};
|
|
||||||
export const builtinComponentSimState: Map<(d: DalBoard) => any> = {
|
|
||||||
"buttonpair": (d: DalBoard) => d.buttonPairState,
|
|
||||||
"ledmatrix": (d: DalBoard) => d.ledMatrixState,
|
|
||||||
"edgeconnector": (d: DalBoard) => d.edgeConnectorState,
|
|
||||||
"serial": (d: DalBoard) => d.serialState,
|
|
||||||
"radio": (d: DalBoard) => d.radioState,
|
|
||||||
"thermometer": (d: DalBoard) => d.thermometerState,
|
|
||||||
"accelerometer": (d: DalBoard) => d.accelerometerState,
|
|
||||||
"compass": (d: DalBoard) => d.compassState,
|
|
||||||
"lightsensor": (d: DalBoard) => d.lightSensorState,
|
|
||||||
"neopixel": (d: DalBoard) => d.neopixelState,
|
|
||||||
};
|
|
||||||
export const builtinComponentPartVisual: Map<(xy: visuals.Coord) => visuals.SVGElAndSize> = {
|
|
||||||
"buttonpair": (xy: visuals.Coord) => visuals.mkBtnSvg(xy),
|
|
||||||
"ledmatrix": (xy: visuals.Coord) => visuals.mkLedMatrixSvg(xy, 8, 8),
|
|
||||||
"neopixel": (xy: visuals.Coord) => visuals.mkNeoPixelPart(xy),
|
|
||||||
};
|
|
||||||
|
|
||||||
//TODO: add multiple board support
|
|
||||||
export const CURRENT_BOARD = MICROBIT_DEF;
|
|
||||||
}
|
|