Compare commits
1 Commits
master
...
orignalmod
Author | SHA1 | Date | |
---|---|---|---|
|
eb660e4a2d |
35
.github/ISSUE_TEMPLATE/bug_report.md
vendored
35
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,35 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
Add screenshots to help explain your problem. You can copy paste the screenshot in the github report. The .gif screen recording is very useful as well.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
17
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,17 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
9
.github/calibre/image-actions.yml
vendored
9
.github/calibre/image-actions.yml
vendored
@ -1,9 +0,0 @@
|
||||
jpeg:
|
||||
quality: 80
|
||||
png:
|
||||
quality: 80
|
||||
webp:
|
||||
quality: 80
|
||||
ignorePaths:
|
||||
- "node_modules/**"
|
||||
- "libs/**"
|
@ -1,16 +0,0 @@
|
||||
name: Compress images
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'docs/**.jpg'
|
||||
- 'docs/**.png'
|
||||
jobs:
|
||||
build:
|
||||
name: calibreapp/image-actions
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: calibreapp/image-actions
|
||||
uses: docker://calibreapp/github-image-actions
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
40
.github/workflows/pxt-buildmain.yml
vendored
40
.github/workflows/pxt-buildmain.yml
vendored
@ -1,40 +0,0 @@
|
||||
name: pxt-buildmain
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'main'
|
||||
create:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: npm install
|
||||
run: |
|
||||
sudo apt-get install xvfb
|
||||
sudo npm install -g pxt
|
||||
npm install
|
||||
- name: pxt ci
|
||||
run: |
|
||||
pxt ci
|
||||
env:
|
||||
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
|
||||
PXT_ACCESS_TOKEN: ${{ secrets.PXT_ACCESS_TOKEN }}
|
||||
PXT_RELEASE_REPO: ${{ secrets.PXT_RELEASE_REPO }}
|
||||
NPM_ACCESS_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
|
||||
CHROME_BIN: chromium-browser
|
||||
DISPLAY: :99.0
|
||||
CI: true
|
31
.github/workflows/pxt-buildpr.yml
vendored
31
.github/workflows/pxt-buildpr.yml
vendored
@ -1,31 +0,0 @@
|
||||
name: pxt-buildpr
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: npm install
|
||||
run: |
|
||||
sudo apt-get install xvfb
|
||||
sudo npm install -g pxt
|
||||
npm install
|
||||
- name: pxt ci
|
||||
run: |
|
||||
pxt ci
|
||||
env:
|
||||
CHROME_BIN: chromium-browser
|
||||
DISPLAY: :99.0
|
||||
CI: true
|
39
.github/workflows/pxt-buildpush.yml
vendored
39
.github/workflows/pxt-buildpush.yml
vendored
@ -1,39 +0,0 @@
|
||||
name: pxt-buildpush
|
||||
|
||||
on:
|
||||
push:
|
||||
# main/master has its own build that includes the crowdin key
|
||||
branches-ignore:
|
||||
- 'main'
|
||||
- 'master'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: npm install
|
||||
run: |
|
||||
sudo apt-get install xvfb
|
||||
sudo npm install -g pxt
|
||||
npm install
|
||||
- name: pxt ci
|
||||
run: |
|
||||
pxt ci
|
||||
env:
|
||||
PXT_ACCESS_TOKEN: ${{ secrets.PXT_ACCESS_TOKEN }}
|
||||
PXT_RELEASE_REPO: ${{ secrets.PXT_RELEASE_REPO }}
|
||||
NPM_ACCESS_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
|
||||
CHROME_BIN: chromium-browser
|
||||
DISPLAY: :99.0
|
||||
CI: true
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -16,8 +16,6 @@ clients/win10/*.opendb
|
||||
clients/**/bin/**
|
||||
clients/**/obj/**
|
||||
clients/electron/projects
|
||||
libs/**/_locales/**
|
||||
package-lock.json
|
||||
|
||||
videos/**
|
||||
|
||||
@ -33,4 +31,3 @@ videos/**
|
||||
lib/
|
||||
.vscode/
|
||||
bin
|
||||
scripts/out.*
|
||||
|
41
README.md
41
README.md
@ -1,34 +1,29 @@
|
||||
# LEGO® MINDSTORMS® Education EV3 for Microsoft MakeCode [![Build Status](https://travis-ci.org/microsoft/pxt-ev3.svg?branch=master)](https://travis-ci.org/microsoft/pxt-ev3)
|
||||
# LEGO Mindstorms EV3 target for PXT
|
||||
|
||||
This repo contains the editor target hosted at https://makecode.mindstorms.com
|
||||
[![Build Status](https://ci2.dot.net/buildStatus/icon?job=Private/pxt_project_pink/master/pxt-ev3_Push)](https://ci2.dot.net/job/Private/job/pxt_project_pink/job/master/job/pxt-ev3_Push/)
|
||||
|
||||
## Local setup
|
||||
This repo contains the editor target hosted at https://lego.makecode.com
|
||||
|
||||
## Local Dev setup
|
||||
|
||||
These instructions assume familiarity with dev tools and languages.
|
||||
|
||||
* install Node.js 8.9.4+
|
||||
* install Docker; make sure `docker` command is in your `PATH`
|
||||
* install Node.js 6+
|
||||
* install [yotta](http://docs.yottabuild.org/#installing)
|
||||
* (optional) install [Visual Studio Code](https://code.visualstudio.com/)
|
||||
|
||||
In a common folder,
|
||||
|
||||
* clone https://github.com/Microsoft/pxt to ``pxt`` folder
|
||||
* clone https://github.com/Microsoft/pxt-common-packages to ``pxt-common-packages`` folder
|
||||
* clone https://github.com/Microsoft/pxt-ev3 to ``pxt-ev3`` folder
|
||||
* go to ``pxt`` and run
|
||||
|
||||
```
|
||||
npm install
|
||||
typings install
|
||||
```
|
||||
|
||||
* to run the local server,
|
||||
```
|
||||
pxt serve --cloud
|
||||
```
|
||||
|
||||
## Local Dev setup
|
||||
|
||||
In the common folder,
|
||||
|
||||
* clone https://github.com/Microsoft/pxt to ``pxt`` folder
|
||||
* clone https://github.com/Microsoft/pxt-common-packages to ``pxt-common-packages`` folder
|
||||
|
||||
* go to ``pxt-common-packages`` and run
|
||||
|
||||
```
|
||||
@ -60,12 +55,18 @@ cd libs/core
|
||||
pxt deploy
|
||||
```
|
||||
|
||||
### Hosted editor
|
||||
|
||||
Currently hosted at:
|
||||
|
||||
https://d541eec2-1e96-4b7b-a223-da9d01d0337a.pxt.io/
|
||||
|
||||
### Jenkins build
|
||||
https://ci2.dot.net/job/Private/job/pxt_project_rainbow/job/master/
|
||||
|
||||
## License
|
||||
MIT
|
||||
|
||||
## Trademarks
|
||||
MICROSOFT, the Microsoft Logo, and MAKECODE are registered trademarks of Microsoft Corporation. They can only be used for the purposes described in and in accordance with Microsoft’s Trademark and Brand guidelines published at https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general.aspx. If the use is not covered in Microsoft’s published guidelines or you are not sure, please consult your legal counsel or the MakeCode team (makecode@microsoft.com).
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
41
SECURITY.md
41
SECURITY.md
@ -1,41 +0,0 @@
|
||||
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK -->
|
||||
|
||||
## Security
|
||||
|
||||
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
||||
|
||||
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
|
||||
|
||||
## Reporting Security Issues
|
||||
|
||||
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||
|
||||
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
|
||||
|
||||
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
|
||||
|
||||
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
|
||||
|
||||
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||
|
||||
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||
* Full paths of source file(s) related to the manifestation of the issue
|
||||
* The location of the affected source code (tag/branch/commit or direct URL)
|
||||
* Any special configuration required to reproduce the issue
|
||||
* Step-by-step instructions to reproduce the issue
|
||||
* Proof-of-concept or exploit code (if possible)
|
||||
* Impact of the issue, including how an attacker might exploit the issue
|
||||
|
||||
This information will help us triage your report more quickly.
|
||||
|
||||
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
|
||||
|
||||
## Preferred Languages
|
||||
|
||||
We prefer all communications to be in English.
|
||||
|
||||
## Policy
|
||||
|
||||
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
|
||||
|
||||
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
12
brick/Makefile
Normal file
12
brick/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
all: mod uf2
|
||||
|
||||
mod:
|
||||
$(MAKE) -C .. MOD=d_usbdev M=`pwd`/kernel ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
|
||||
@mkdir -p bin
|
||||
cp kernel/*.ko bin/
|
||||
|
||||
uf2:
|
||||
$(MAKE) -C uf2daemon
|
||||
@mkdir -p bin
|
||||
cp uf2daemon/server bin/uf2d
|
||||
|
34
brick/README.md
Normal file
34
brick/README.md
Normal file
@ -0,0 +1,34 @@
|
||||
# Support code to run on EV3 brick
|
||||
|
||||
## Kernel module
|
||||
|
||||
Kernel module is based on LEGO's `d_usbdev` module, with the addition of slightly modified `g_mass_storage`
|
||||
module from the Linux kernel. The module and supporting sources are licensed under GPLv2 (since
|
||||
they are derived from GPLv2 code).
|
||||
|
||||
### Modifications
|
||||
|
||||
* the `d_usbdev` uses the composite framework to register an additional mass storage function in addtion
|
||||
to the pre-existing custom USB HID function
|
||||
* the `g_mass_storage` module has the following changes:
|
||||
* a bug fixed, where page-misaligned writes would hang
|
||||
* additional `/sys/.../lun0/active` entry is added, which allows for signaling drive eject to the host
|
||||
|
||||
### Kernel modifications
|
||||
|
||||
The kernel itself has modified FIFO queue sizes. The LEGO kernel uses `1024` for `ep1in` and `ep1out`,
|
||||
and then `64` for `ep2` and `ep3`. Note that this is non-standard modification done with a kernel patch,
|
||||
that I didn't manage to find. The MSD requires `512` for `ep2` and `ep3`. I have binary edited the kernel
|
||||
to do so.
|
||||
|
||||
Note that there's 4k of FIFO memory in the hardware. If you set the queue sizes with a sum of more than
|
||||
4k, the kernel will hang, and you will not know why.
|
||||
|
||||
## UF2 Daemon
|
||||
|
||||
The [UF2](https://github.com/Microsoft/uf2) daemon is based on
|
||||
[UF2 ATSAMD21](https://github.com/Microsoft/uf2-samd21) bootloader code. It exposes a virtual
|
||||
FAT16 file system over Linux Network Block Device interface (`/dev/nbd0` to be precise).
|
||||
This device is then exposed via the `g_mass_storage` module to the host computer.
|
||||
|
||||
The Daemon is licensed under MIT.
|
9
brick/ins
Executable file
9
brick/ins
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
set -ex
|
||||
cd /mnt/ramdisk/prjs/ko
|
||||
echo 3 > /proc/sys/kernel/printk
|
||||
insmod ./nbd.ko
|
||||
sleep 1
|
||||
./uf2d > /tmp/uf2d.log 2> /tmp/uf2derr.log
|
||||
sleep 1
|
||||
insmod ./d_usbdev.ko file=/dev/nbd0 HostStr=EV3 SerialStr=0016535543af
|
2
brick/kernel/Makefile
Normal file
2
brick/kernel/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
obj-m += $(MOD).o
|
||||
|
1370
brick/kernel/computil.c
Normal file
1370
brick/kernel/computil.c
Normal file
File diff suppressed because it is too large
Load Diff
698
brick/kernel/d_usbdev.c
Normal file
698
brick/kernel/d_usbdev.c
Normal file
@ -0,0 +1,698 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This UsbDev file is based on and inheritated from
|
||||
* the original file (zero.c) and work done by David Brownell
|
||||
*
|
||||
* >> zero.c -- Gadget Zero, for USB development <<
|
||||
*
|
||||
* >> Copyright (C) 2003-2008 David Brownell <<
|
||||
* >> Copyright (C) 2008 by Nokia Corporation <<
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \page UsbdevModule USB device Module
|
||||
*
|
||||
*
|
||||
*- \subpage UsbdevModuleResources
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PCASM
|
||||
#include <asm/types.h>
|
||||
#endif
|
||||
|
||||
#include "../../lms2012/source/lms2012.h"
|
||||
#include "../../lms2012/source/am1808.h"
|
||||
|
||||
|
||||
#define MODULE_NAME "usbdev_module"
|
||||
#define DEVICE1_NAME USBDEV_DEVICE
|
||||
|
||||
|
||||
|
||||
static int ModuleInit(void);
|
||||
static void ModuleExit(void);
|
||||
|
||||
#define __USE_POSIX
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
|
||||
#ifndef PCASM
|
||||
#include <linux/hrtimer.h>
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/hrtimer.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include <linux/ioport.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include "computil.c" // The composite framework used as utility file
|
||||
#include <../drivers/usb/gadget/gadget_chips.h>
|
||||
#include <../drivers/usb/gadget/usbstring.c>
|
||||
#include <../drivers/usb/gadget/config.c>
|
||||
#include <../drivers/usb/gadget/epautoconf.c>
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Kbuild is not very cooperative with respect to linking separately
|
||||
* compiled library objects into one module. So for now we won't use
|
||||
* separate compilation ... ensuring init/exit sections work to shrink
|
||||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
|
||||
#include <../drivers/usb/gadget/g_zero.h>
|
||||
#define MAX_EP_SIZE 1024
|
||||
#define MAX_FULLSPEED_EP_SIZE 64
|
||||
unsigned buflen = MAX_EP_SIZE ;
|
||||
char usb_char_buffer_in[MAX_EP_SIZE];
|
||||
char usb_full_buffer_in[MAX_FULLSPEED_EP_SIZE];
|
||||
int usb_char_in_length = 0;
|
||||
char usb_char_buffer_out[MAX_EP_SIZE];
|
||||
char usb_full_buffer_out[MAX_FULLSPEED_EP_SIZE];
|
||||
int usb_char_out_length = 0;
|
||||
|
||||
#define SHM_LENGTH (sizeof(UsbSpeedDefault))
|
||||
#define NPAGES ((SHM_LENGTH + PAGE_SIZE - 1) / PAGE_SIZE)
|
||||
static void *kmalloc_ptr;
|
||||
|
||||
#include "usb_function.c" // Specific USB functionality
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("The LEGO Group");
|
||||
MODULE_DESCRIPTION(MODULE_NAME);
|
||||
MODULE_SUPPORTED_DEVICE(DEVICE1_NAME);
|
||||
|
||||
module_init(ModuleInit);
|
||||
module_exit(ModuleExit);
|
||||
|
||||
#else
|
||||
// Keep Eclipse happy
|
||||
#endif
|
||||
|
||||
// USB main stuff
|
||||
|
||||
#define DRIVER_VERSION "31jan2011->"
|
||||
|
||||
#ifndef PCASM
|
||||
module_param(buflen, uint, 0);
|
||||
#else
|
||||
// Keep Eclipse happy
|
||||
#endif
|
||||
|
||||
static int loopdefault = 0;
|
||||
#ifndef PCASM
|
||||
module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
|
||||
#else
|
||||
// Keep Eclipse happy
|
||||
#endif
|
||||
|
||||
#define DRIVER_VENDOR_NUM 0x0694 // LEGO Group
|
||||
#define DRIVER_PRODUCT_NUM 0x0005 // No. 5 in a row
|
||||
#define DEFAULT_AUTORESUME 0
|
||||
|
||||
/* If the optional "autoresume" mode is enabled, it provides good
|
||||
* functional coverage for the "USBCV" test harness from USB-IF.
|
||||
* It's always set if OTG mode is enabled.
|
||||
*/
|
||||
|
||||
unsigned autoresume = DEFAULT_AUTORESUME;
|
||||
module_param(autoresume, uint, S_IRUGO);
|
||||
|
||||
#ifndef PCASM
|
||||
MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
|
||||
#else
|
||||
// Keep Eclipse happy
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static struct usb_device_descriptor device_desc = {
|
||||
.bLength = sizeof device_desc,
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
|
||||
.bcdUSB = cpu_to_le16(0x0200),
|
||||
.bDeviceClass = 0,
|
||||
.bDeviceSubClass = 0,
|
||||
.bDeviceProtocol = 0,
|
||||
/*.bMaxPacketSize0 = f(hardware) */
|
||||
.idVendor = cpu_to_le16(DRIVER_VENDOR_NUM),
|
||||
.idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM),
|
||||
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USB_OTG
|
||||
struct usb_otg_descriptor otg_descriptor = {
|
||||
.bLength = sizeof otg_descriptor,
|
||||
.bDescriptorType = USB_DT_OTG,
|
||||
|
||||
/* REVISIT SRP-only hardware is possible, although
|
||||
* it would not be called "OTG" ...
|
||||
*/
|
||||
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
|
||||
};
|
||||
|
||||
const struct usb_descriptor_header *otg_desc[] = {
|
||||
(struct usb_descriptor_header *) &otg_descriptor,
|
||||
NULL,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* string IDs are assigned dynamically */
|
||||
|
||||
#define STRING_MANUFACTURER_IDX 0
|
||||
#define STRING_PRODUCT_IDX 1
|
||||
#define STRING_SERIAL_IDX 2
|
||||
|
||||
static char manufacturer[] = "LEGO Group";
|
||||
static char serial[] = "123456789ABC ";
|
||||
static char longname[] = "EV3 brick ";
|
||||
|
||||
static struct usb_string strings_dev[3] = {
|
||||
[STRING_MANUFACTURER_IDX].s = manufacturer,
|
||||
[STRING_PRODUCT_IDX].s = longname,
|
||||
[STRING_SERIAL_IDX].s = serial
|
||||
};
|
||||
|
||||
|
||||
static struct usb_gadget_strings stringtab_dev = {
|
||||
.language = 0x0409, /* en-us */
|
||||
.strings = strings_dev,
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings *dev_strings[] = {
|
||||
&stringtab_dev,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
struct usb_request *alloc_ep_req(struct usb_ep *ep)
|
||||
{
|
||||
struct usb_request *req;
|
||||
|
||||
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
|
||||
if (req) {
|
||||
req->length = buflen;
|
||||
req->buf = kmalloc(buflen, GFP_ATOMIC);
|
||||
if (!req->buf) {
|
||||
usb_ep_free_request(ep, req);
|
||||
req = NULL;
|
||||
}
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
void free_ep_req(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
kfree(req->buf);
|
||||
usb_ep_free_request(ep, req);
|
||||
}
|
||||
|
||||
static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
|
||||
{
|
||||
int value;
|
||||
|
||||
if (ep->driver_data) {
|
||||
value = usb_ep_disable(ep);
|
||||
if (value < 0)
|
||||
DBG(cdev, "disable %s --> %d\n",
|
||||
ep->name, value);
|
||||
ep->driver_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void disable_endpoints(struct usb_composite_dev *cdev,
|
||||
struct usb_ep *in, struct usb_ep *out)
|
||||
{
|
||||
disable_ep(cdev, in);
|
||||
disable_ep(cdev, out);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static struct timer_list autoresume_timer;
|
||||
|
||||
static void zero_autoresume(unsigned long _c)
|
||||
{
|
||||
struct usb_composite_dev *cdev = (void *)_c;
|
||||
struct usb_gadget *g = cdev->gadget;
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("zero_autoresume\n\r");
|
||||
#endif
|
||||
|
||||
/* unconfigured devices can't issue wakeups */
|
||||
if (!cdev->config)
|
||||
return;
|
||||
|
||||
/* Normally the host would be woken up for something
|
||||
* more significant than just a timer firing; likely
|
||||
* because of some direct user request.
|
||||
*/
|
||||
if (g->speed != USB_SPEED_UNKNOWN) {
|
||||
int status = usb_gadget_wakeup(g);
|
||||
INFO(cdev, "%s --> %d\n", __func__, status);
|
||||
}
|
||||
}
|
||||
|
||||
static void zero_suspend(struct usb_composite_dev *cdev)
|
||||
{
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("zero_suspend\n\r");
|
||||
#endif
|
||||
|
||||
if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
|
||||
return;
|
||||
|
||||
if (autoresume) {
|
||||
mod_timer(&autoresume_timer, jiffies + (HZ * autoresume));
|
||||
DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume);
|
||||
} else
|
||||
DBG(cdev, "%s\n", __func__);
|
||||
}
|
||||
|
||||
static void zero_resume(struct usb_composite_dev *cdev)
|
||||
{
|
||||
DBG(cdev, "%s\n", __func__);
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("zero_resume\n\r");
|
||||
#endif
|
||||
|
||||
del_timer(&autoresume_timer);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int zero_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
int gcnum;
|
||||
struct usb_gadget *gadget = cdev->gadget;
|
||||
int id;
|
||||
|
||||
/* Allocate string descriptor numbers ... note that string
|
||||
* contents can be overridden by the composite_dev glue.
|
||||
*/
|
||||
id = usb_string_id(cdev);
|
||||
if (id < 0)
|
||||
return id;
|
||||
|
||||
strings_dev[STRING_MANUFACTURER_IDX].id = id;
|
||||
device_desc.iManufacturer = id;
|
||||
|
||||
id = usb_string_id(cdev);
|
||||
if (id < 0)
|
||||
return id;
|
||||
|
||||
|
||||
strings_dev[STRING_PRODUCT_IDX].id = id;
|
||||
device_desc.iProduct = id;
|
||||
|
||||
id = usb_string_id(cdev);
|
||||
if (id < 0)
|
||||
return id;
|
||||
|
||||
|
||||
strings_dev[STRING_SERIAL_IDX].id = id;
|
||||
device_desc.iSerialNumber = id;
|
||||
|
||||
setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
|
||||
|
||||
rudolf_add(cdev, autoresume != 0);
|
||||
|
||||
gcnum = usb_gadget_controller_number(gadget);
|
||||
if (gcnum >= 0)
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
|
||||
else {
|
||||
/* gadget zero is so simple (for now, no altsettings) that
|
||||
* it SHOULD NOT have problems with bulk-capable hardware.
|
||||
* so just warn about unrcognized controllers -- don't panic.
|
||||
*
|
||||
* things like configuration and altsetting numbering
|
||||
* can need hardware-specific attention though.
|
||||
*/
|
||||
pr_warning("%s: controller '%s' not recognized\n",
|
||||
longname, gadget->name);
|
||||
device_desc.bcdDevice = cpu_to_le16(0x9999);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zero_unbind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("zero_unbind\n\r");
|
||||
#endif
|
||||
|
||||
del_timer_sync(&autoresume_timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_composite_driver zero_driver = {
|
||||
.name = "zero",
|
||||
.dev = &device_desc,
|
||||
.strings = dev_strings,
|
||||
.bind = zero_bind,
|
||||
.unbind = zero_unbind,
|
||||
.suspend = zero_suspend,
|
||||
.resume = zero_resume,
|
||||
};
|
||||
|
||||
static int dUsbInit(void)
|
||||
{
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("dUsbInit\n\r");
|
||||
#endif
|
||||
|
||||
UsbSpeed.Speed = FULL_SPEED; // default to FULL_SPEED if not connected to a HIGH-SPEED
|
||||
(*pUsbSpeed).Speed = FULL_SPEED; // HOST. If not connected to HIGH-SPEED we assume we're
|
||||
// wanting (or at least doing) Daisy Chain
|
||||
return usb_composite_register(&zero_driver);
|
||||
}
|
||||
|
||||
static void dUsbExit(void)
|
||||
{
|
||||
usb_composite_unregister(&zero_driver);
|
||||
}
|
||||
|
||||
// DEVICE1 char device stuff ********************************************************************
|
||||
|
||||
static ssize_t Device1Write(struct file *File,const char *Buffer,size_t Count,loff_t *Data)
|
||||
{
|
||||
// Write data for the HOST to poll - Stuff sent to the HOST
|
||||
|
||||
int BytesWritten = 0;
|
||||
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("Device1Write - usb_char_in_length = %d\n", usb_char_in_length);
|
||||
#endif
|
||||
|
||||
if (usb_char_in_length == 0) // ready for more
|
||||
{ // else wait in USER layer
|
||||
BytesWritten = Count;
|
||||
copy_from_user(usb_char_buffer_in, Buffer, BytesWritten);
|
||||
usb_char_in_length = BytesWritten;
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("WR = %d, %d -- ", usb_char_buffer_in[2], usb_char_buffer_in[3]);
|
||||
#endif
|
||||
|
||||
if(USB_DATA_PENDING == input_state)
|
||||
{
|
||||
// Already we've a failed tx (HOST part starwing??
|
||||
|
||||
input_state = USB_DATA_READY;
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("DATA_PENDING SECOND time and reset!! in Device1Write\n\r");
|
||||
#endif
|
||||
}
|
||||
|
||||
if(USB_DATA_READY == input_state)
|
||||
{
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("USB_DATA_READY in Device1Write\n\r");
|
||||
#endif
|
||||
|
||||
input_state = USB_DATA_BUSY;
|
||||
write_data_to_the_host(save_in_ep, save_in_req);
|
||||
usb_req_arm(save_in_ep, save_in_req); // new request
|
||||
}
|
||||
else
|
||||
{
|
||||
input_state = USB_DATA_PENDING;
|
||||
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("DATA_PENDING in Device1Write\n\r");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("usbdev %d written\n\r", BytesWritten);
|
||||
#endif
|
||||
|
||||
return (BytesWritten); // Zero means USB was not ready yet
|
||||
}
|
||||
|
||||
static ssize_t Device1Read(struct file *File,char *Buffer,size_t Count,loff_t *Offset)
|
||||
{
|
||||
// Read the bits'n'bytes from the HOST
|
||||
int BytesRead = 0;
|
||||
|
||||
if (usb_char_out_length > 0) // Something to look at
|
||||
{
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("Some bytes to READ?\n\r");
|
||||
#endif
|
||||
|
||||
copy_to_user(Buffer, usb_char_buffer_out, Count);
|
||||
BytesRead = usb_char_out_length;
|
||||
usb_char_out_length = 0;
|
||||
}
|
||||
return (BytesRead);
|
||||
}
|
||||
|
||||
static int Device1Mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = remap_pfn_range(vma,vma->vm_start,virt_to_phys((void*)((unsigned long)pUsbSpeed)) >> PAGE_SHIFT,vma->vm_end-vma->vm_start,PAGE_SHARED);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
ret = -EAGAIN;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
static const struct file_operations Device1Entries =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
.read = Device1Read,
|
||||
.write = Device1Write,
|
||||
.mmap = Device1Mmap
|
||||
};
|
||||
|
||||
|
||||
static struct miscdevice Device1 =
|
||||
{
|
||||
MISC_DYNAMIC_MINOR,
|
||||
DEVICE1_NAME,
|
||||
&Device1Entries
|
||||
};
|
||||
|
||||
|
||||
static int Device1Init(void)
|
||||
{
|
||||
int Result = -1;
|
||||
UWORD *pTemp;
|
||||
int i;
|
||||
|
||||
Result = misc_register(&Device1);
|
||||
if (Result)
|
||||
{
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk(" %s device register failed\n",DEVICE1_NAME);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk(" %s device register OK\n",DEVICE1_NAME);
|
||||
#endif
|
||||
|
||||
// allocate kernel shared memory for DaisyChain Speed info
|
||||
|
||||
if ((kmalloc_ptr = kmalloc((NPAGES + 2) * PAGE_SIZE, GFP_KERNEL)) != NULL)
|
||||
{
|
||||
|
||||
pTemp = (UWORD*)((((unsigned long)kmalloc_ptr) + PAGE_SIZE - 1) & PAGE_MASK);
|
||||
|
||||
for (i = 0; i < NPAGES * PAGE_SIZE; i += PAGE_SIZE)
|
||||
{
|
||||
SetPageReserved(virt_to_page(((unsigned long)pTemp) + i));
|
||||
}
|
||||
|
||||
pUsbSpeed = (USB_SPEED*)pTemp;
|
||||
}
|
||||
|
||||
dUsbInit();
|
||||
}
|
||||
|
||||
return (Result);
|
||||
}
|
||||
|
||||
static void Device1Exit(void)
|
||||
{
|
||||
int i;
|
||||
UWORD *pTemp = (UWORD*)pUsbSpeed;
|
||||
|
||||
dUsbExit();
|
||||
|
||||
pUsbSpeed = &UsbSpeedDefault;
|
||||
|
||||
for (i = 0; i < NPAGES * PAGE_SIZE; i+= PAGE_SIZE)
|
||||
{
|
||||
ClearPageReserved(virt_to_page(((unsigned long)pTemp) + i));
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk(" %s memory page %d unmapped\n",DEVICE1_NAME,i);
|
||||
#endif
|
||||
}
|
||||
|
||||
kfree(kmalloc_ptr);
|
||||
|
||||
misc_deregister(&Device1);
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk(" %s device unregistered\n",DEVICE1_NAME);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// MODULE *********************************************************************
|
||||
|
||||
char *HostStr; // Used for HostName - or NOT used at all
|
||||
char *SerialStr; // Used for Serial number (I.e. BT number)
|
||||
|
||||
module_param (HostStr, charp, 0);
|
||||
module_param (SerialStr, charp, 0);
|
||||
|
||||
static int ModuleInit(void)
|
||||
{
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("%s Module init started\r\n",MODULE_NAME);
|
||||
#endif
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("This is DEFAULT NAME: %s\n\r", longname);
|
||||
#endif
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("\n\rThis is the HostStr: %s\n\r", HostStr);
|
||||
#endif
|
||||
|
||||
strcpy(longname, HostStr);
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("\n\rThis is the INSMODed NAME: %s\n\r", longname);
|
||||
#endif
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("\n\rThis is the DEFAULT SerialNumber: %s\n\r", serial);
|
||||
#endif
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("\n\rThis is the SerialStr: %s\n\r", SerialStr);
|
||||
#endif
|
||||
|
||||
strcpy(serial, SerialStr);
|
||||
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("\n\rThis is the INSMODed SerialNumber (BT mac): %s\n\r", serial);
|
||||
#endif
|
||||
|
||||
Device1Init();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void ModuleExit(void)
|
||||
{
|
||||
//#define DEBUG
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("%s exit started\n",MODULE_NAME);
|
||||
#endif
|
||||
|
||||
Device1Exit();
|
||||
|
||||
}
|
||||
|
3091
brick/kernel/f_mass_storage.c
Normal file
3091
brick/kernel/f_mass_storage.c
Normal file
File diff suppressed because it is too large
Load Diff
276
brick/kernel/gadget_chips.h
Normal file
276
brick/kernel/gadget_chips.h
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* USB device controllers have lots of quirks. Use these macros in
|
||||
* gadget drivers or other code that needs to deal with them, and which
|
||||
* autoconfigures instead of using early binding to the hardware.
|
||||
*
|
||||
* This SHOULD eventually work like the ARM mach_is_*() stuff, driven by
|
||||
* some config file that gets updated as new hardware is supported.
|
||||
* (And avoiding all runtime comparisons in typical one-choice configs!)
|
||||
*
|
||||
* NOTE: some of these controller drivers may not be available yet.
|
||||
* Some are available on 2.4 kernels; several are available, but not
|
||||
* yet pushed in the 2.6 mainline tree.
|
||||
*/
|
||||
|
||||
#ifndef __GADGET_CHIPS_H
|
||||
#define __GADGET_CHIPS_H
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_NET2280
|
||||
#define gadget_is_net2280(g) !strcmp("net2280", (g)->name)
|
||||
#else
|
||||
#define gadget_is_net2280(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_AMD5536UDC
|
||||
#define gadget_is_amd5536udc(g) !strcmp("amd5536udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_amd5536udc(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_DUMMY_HCD
|
||||
#define gadget_is_dummy(g) !strcmp("dummy_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_dummy(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_PXA25X
|
||||
#define gadget_is_pxa(g) !strcmp("pxa25x_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_pxa(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_GOKU
|
||||
#define gadget_is_goku(g) !strcmp("goku_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_goku(g) 0
|
||||
#endif
|
||||
|
||||
/* SH3 UDC -- not yet ported 2.4 --> 2.6 */
|
||||
#ifdef CONFIG_USB_GADGET_SUPERH
|
||||
#define gadget_is_sh(g) !strcmp("sh_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_sh(g) 0
|
||||
#endif
|
||||
|
||||
/* not yet stable on 2.6 (would help "original Zaurus") */
|
||||
#ifdef CONFIG_USB_GADGET_SA1100
|
||||
#define gadget_is_sa1100(g) !strcmp("sa1100_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_sa1100(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_LH7A40X
|
||||
#define gadget_is_lh7a40x(g) !strcmp("lh7a40x_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_lh7a40x(g) 0
|
||||
#endif
|
||||
|
||||
/* handhelds.org tree (?) */
|
||||
#ifdef CONFIG_USB_GADGET_MQ11XX
|
||||
#define gadget_is_mq11xx(g) !strcmp("mq11xx_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_mq11xx(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_OMAP
|
||||
#define gadget_is_omap(g) !strcmp("omap_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_omap(g) 0
|
||||
#endif
|
||||
|
||||
/* not yet ported 2.4 --> 2.6 */
|
||||
#ifdef CONFIG_USB_GADGET_N9604
|
||||
#define gadget_is_n9604(g) !strcmp("n9604_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_n9604(g) 0
|
||||
#endif
|
||||
|
||||
/* various unstable versions available */
|
||||
#ifdef CONFIG_USB_GADGET_PXA27X
|
||||
#define gadget_is_pxa27x(g) !strcmp("pxa27x_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_pxa27x(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_ATMEL_USBA
|
||||
#define gadget_is_atmel_usba(g) !strcmp("atmel_usba_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_atmel_usba(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_S3C2410
|
||||
#define gadget_is_s3c2410(g) !strcmp("s3c2410_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_s3c2410(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_AT91
|
||||
#define gadget_is_at91(g) !strcmp("at91_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_at91(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_IMX
|
||||
#define gadget_is_imx(g) !strcmp("imx_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_imx(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_FSL_USB2
|
||||
#define gadget_is_fsl_usb2(g) !strcmp("fsl-usb2-udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_fsl_usb2(g) 0
|
||||
#endif
|
||||
|
||||
/* Mentor high speed function controller */
|
||||
/* from Montavista kernel (?) */
|
||||
#ifdef CONFIG_USB_GADGET_MUSBHSFC
|
||||
#define gadget_is_musbhsfc(g) !strcmp("musbhsfc_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_musbhsfc(g) 0
|
||||
#endif
|
||||
|
||||
/* Mentor high speed "dual role" controller, in peripheral role */
|
||||
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
|
||||
#define gadget_is_musbhdrc(g) !strcmp("musb_hdrc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_musbhdrc(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_LANGWELL
|
||||
#define gadget_is_langwell(g) (!strcmp("langwell_udc", (g)->name))
|
||||
#else
|
||||
#define gadget_is_langwell(g) 0
|
||||
#endif
|
||||
|
||||
/* from Montavista kernel (?) */
|
||||
#ifdef CONFIG_USB_GADGET_MPC8272
|
||||
#define gadget_is_mpc8272(g) !strcmp("mpc8272_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_mpc8272(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_M66592
|
||||
#define gadget_is_m66592(g) !strcmp("m66592_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_m66592(g) 0
|
||||
#endif
|
||||
|
||||
/* Freescale CPM/QE UDC SUPPORT */
|
||||
#ifdef CONFIG_USB_GADGET_FSL_QE
|
||||
#define gadget_is_fsl_qe(g) !strcmp("fsl_qe_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_fsl_qe(g) 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_CI13XXX
|
||||
#define gadget_is_ci13xxx(g) (!strcmp("ci13xxx_udc", (g)->name))
|
||||
#else
|
||||
#define gadget_is_ci13xxx(g) 0
|
||||
#endif
|
||||
|
||||
// CONFIG_USB_GADGET_SX2
|
||||
// CONFIG_USB_GADGET_AU1X00
|
||||
// ...
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_R8A66597
|
||||
#define gadget_is_r8a66597(g) !strcmp("r8a66597_udc", (g)->name)
|
||||
#else
|
||||
#define gadget_is_r8a66597(g) 0
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* usb_gadget_controller_number - support bcdDevice id convention
|
||||
* @gadget: the controller being driven
|
||||
*
|
||||
* Return a 2-digit BCD value associated with the peripheral controller,
|
||||
* suitable for use as part of a bcdDevice value, or a negative error code.
|
||||
*
|
||||
* NOTE: this convention is purely optional, and has no meaning in terms of
|
||||
* any USB specification. If you want to use a different convention in your
|
||||
* gadget driver firmware -- maybe a more formal revision ID -- feel free.
|
||||
*
|
||||
* Hosts see these bcdDevice numbers, and are allowed (but not encouraged!)
|
||||
* to change their behavior accordingly. For example it might help avoiding
|
||||
* some chip bug.
|
||||
*/
|
||||
static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
|
||||
{
|
||||
if (gadget_is_net2280(gadget))
|
||||
return 0x01;
|
||||
else if (gadget_is_dummy(gadget))
|
||||
return 0x02;
|
||||
else if (gadget_is_pxa(gadget))
|
||||
return 0x03;
|
||||
else if (gadget_is_sh(gadget))
|
||||
return 0x04;
|
||||
else if (gadget_is_sa1100(gadget))
|
||||
return 0x05;
|
||||
else if (gadget_is_goku(gadget))
|
||||
return 0x06;
|
||||
else if (gadget_is_mq11xx(gadget))
|
||||
return 0x07;
|
||||
else if (gadget_is_omap(gadget))
|
||||
return 0x08;
|
||||
else if (gadget_is_lh7a40x(gadget))
|
||||
return 0x09;
|
||||
else if (gadget_is_n9604(gadget))
|
||||
return 0x10;
|
||||
else if (gadget_is_pxa27x(gadget))
|
||||
return 0x11;
|
||||
else if (gadget_is_s3c2410(gadget))
|
||||
return 0x12;
|
||||
else if (gadget_is_at91(gadget))
|
||||
return 0x13;
|
||||
else if (gadget_is_imx(gadget))
|
||||
return 0x14;
|
||||
else if (gadget_is_musbhsfc(gadget))
|
||||
return 0x15;
|
||||
else if (gadget_is_musbhdrc(gadget))
|
||||
return 0x16;
|
||||
else if (gadget_is_mpc8272(gadget))
|
||||
return 0x17;
|
||||
else if (gadget_is_atmel_usba(gadget))
|
||||
return 0x18;
|
||||
else if (gadget_is_fsl_usb2(gadget))
|
||||
return 0x19;
|
||||
else if (gadget_is_amd5536udc(gadget))
|
||||
return 0x20;
|
||||
else if (gadget_is_m66592(gadget))
|
||||
return 0x21;
|
||||
else if (gadget_is_fsl_qe(gadget))
|
||||
return 0x22;
|
||||
else if (gadget_is_ci13xxx(gadget))
|
||||
return 0x23;
|
||||
else if (gadget_is_langwell(gadget))
|
||||
return 0x24;
|
||||
else if (gadget_is_r8a66597(gadget))
|
||||
return 0x25;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gadget_supports_altsettings - return true if altsettings work
|
||||
* @gadget: the gadget in question
|
||||
*/
|
||||
static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
|
||||
{
|
||||
/* PXA 21x/25x/26x has no altsettings at all */
|
||||
if (gadget_is_pxa(gadget))
|
||||
return false;
|
||||
|
||||
/* PXA 27x and 3xx have *broken* altsetting support */
|
||||
if (gadget_is_pxa27x(gadget))
|
||||
return false;
|
||||
|
||||
/* SH3 hardware just doesn't do altsettings */
|
||||
if (gadget_is_sh(gadget))
|
||||
return false;
|
||||
|
||||
/* Everything else is *presumably* fine ... */
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* __GADGET_CHIPS_H */
|
249
brick/kernel/source/am1808.h
Executable file
249
brick/kernel/source/am1808.h
Executable file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef AM1808_H_
|
||||
#define AM1808_H_
|
||||
|
||||
#ifndef PCASM
|
||||
#include <mach/da8xx.h>
|
||||
#else
|
||||
#define __iomem
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
GP0_0,GP0_1,GP0_2,GP0_3,GP0_4,GP0_5,GP0_6,GP0_7,GP0_8,GP0_9,GP0_10,GP0_11,GP0_12,GP0_13,GP0_14,GP0_15,
|
||||
GP1_0,GP1_1,GP1_2,GP1_3,GP1_4,GP1_5,GP1_6,GP1_7,GP1_8,GP1_9,GP1_10,GP1_11,GP1_12,GP1_13,GP1_14,GP1_15,
|
||||
GP2_0,GP2_1,GP2_2,GP2_3,GP2_4,GP2_5,GP2_6,GP2_7,GP2_8,GP2_9,GP2_10,GP2_11,GP2_12,GP2_13,GP2_14,GP2_15,
|
||||
GP3_0,GP3_1,GP3_2,GP3_3,GP3_4,GP3_5,GP3_6,GP3_7,GP3_8,GP3_9,GP3_10,GP3_11,GP3_12,GP3_13,GP3_14,GP3_15,
|
||||
GP4_0,GP4_1,GP4_2,GP4_3,GP4_4,GP4_5,GP4_6,GP4_7,GP4_8,GP4_9,GP4_10,GP4_11,GP4_12,GP4_13,GP4_14,GP4_15,
|
||||
GP5_0,GP5_1,GP5_2,GP5_3,GP5_4,GP5_5,GP5_6,GP5_7,GP5_8,GP5_9,GP5_10,GP5_11,GP5_12,GP5_13,GP5_14,GP5_15,
|
||||
GP6_0,GP6_1,GP6_2,GP6_3,GP6_4,GP6_5,GP6_6,GP6_7,GP6_8,GP6_9,GP6_10,GP6_11,GP6_12,GP6_13,GP6_14,GP6_15,
|
||||
GP7_0,GP7_1,GP7_2,GP7_3,GP7_4,GP7_5,GP7_6,GP7_7,GP7_8,GP7_9,GP7_10,GP7_11,GP7_12,GP7_13,GP7_14,GP7_15,
|
||||
GP8_0,GP8_1,GP8_2,GP8_3,GP8_4,GP8_5,GP8_6,GP8_7,GP8_8,GP8_9,GP8_10,GP8_11,GP8_12,GP8_13,GP8_14,GP8_15,
|
||||
NO_OF_GPIOS,
|
||||
UART0_TXD,UART0_RXD,UART1_TXD,UART1_RXD,
|
||||
SPI0_MOSI,SPI0_MISO,SPI0_SCL,SPI0_CS,
|
||||
SPI1_MOSI,SPI1_MISO,SPI1_SCL,SPI1_CS,
|
||||
EPWM1A,EPWM1B,APWM0,APWM1,EPWM0B,AXR3,AXR4
|
||||
};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int Pin;
|
||||
u16 MuxReg;
|
||||
u32 Mask;
|
||||
u32 Mode;
|
||||
}
|
||||
MRM;
|
||||
|
||||
MRM MuxRegMap[] =
|
||||
{ // Pin MuxReg Mask Mode
|
||||
|
||||
{ GP0_1 , 1, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP0_2 , 1, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP0_3 , 1, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP0_4 , 1, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP0_5 , 1, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP0_6 , 1, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP0_7 , 1, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP0_11, 0, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP0_12, 0, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP0_13, 0, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP0_14, 0, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP0_15, 0, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP1_0 , 4, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP1_8 , 3, 0xFFFFFFF0, 0x00000004 },
|
||||
|
||||
{ GP1_9, 2, 0xF0FFFFFF, 0x04000000 },
|
||||
{ GP1_10, 2, 0xFF0FFFFF, 0x00400000 },
|
||||
{ GP1_11, 2, 0xFFF0FFFF, 0x00040000 },
|
||||
{ GP1_12, 2, 0xFFFF0FFF, 0x00004000 },
|
||||
{ GP1_13, 2, 0xFFFFF0FF, 0x00000400 },
|
||||
{ GP1_14, 2, 0xFFFFFF0F, 0x00000040 },
|
||||
{ GP1_15, 2, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP2_0, 6, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP2_1, 6, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP2_2, 6, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP2_3, 6, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP2_4, 6, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP2_5, 6, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP2_6, 6, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP2_7, 6, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP2_8, 5, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP2_9, 5, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP2_10, 5, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP2_11, 5, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP2_12, 5, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP2_13, 5, 0xFFFFF0FF, 0x00000800 },
|
||||
|
||||
{ GP3_0, 8, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP3_1 , 8, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP3_2, 8, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP3_3, 8, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP3_4, 8, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP3_5, 8, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP3_6, 8, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP3_7, 8, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP3_8, 7, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP3_9, 7, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP3_10, 7, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP3_11, 7, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP3_12, 7, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP3_13, 7, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP3_14, 7, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP3_15, 7, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP4_1, 10, 0xF0FFFFFF, 0x08000000 },
|
||||
|
||||
{ GP4_8, 9, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP4_9, 9, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP4_10, 9, 0xFF0FFFFF, 0x00800000 },
|
||||
|
||||
{ GP4_12, 9, 0xFFFF0FFF, 0x00008000 },
|
||||
|
||||
{ GP4_14, 9, 0xFFFFFF0F, 0x00000080 },
|
||||
|
||||
{ GP5_0, 12, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP5_1, 12, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP5_2, 12, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP5_3, 12, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP5_4, 12, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP5_5, 12, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP5_6, 12, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP5_7, 12, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP5_8, 11, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP5_9, 11, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP5_10, 11, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP5_11, 11, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP5_12, 11, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP5_13, 11, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP5_14, 11, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP5_15, 11, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP6_0 , 19, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP6_1, 19, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP6_2, 19, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP6_3, 19, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP6_4, 19, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP6_5, 16, 0xFFFFFF0F, 0x00000080 },
|
||||
|
||||
{ GP6_6, 14, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP6_7, 14, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP6_8, 13, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP6_9, 13, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP6_10, 13, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP6_11, 13, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP6_12, 13, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP6_13, 13, 0xFFFFF0FF, 0x00000800 },
|
||||
{ GP6_14, 13, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP6_15, 13, 0xFFFFFFF0, 0x00000008 },
|
||||
|
||||
{ GP7_4, 17, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP7_8, 17, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP7_9, 17, 0xFFFFFFF0, 0x00000008 },
|
||||
{ GP7_10, 16, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP7_11, 16, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP7_12, 16, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP7_13, 16, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP7_14, 16, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP7_15, 16, 0xFFFFF0FF, 0x00000800 },
|
||||
|
||||
{ GP8_2 , 3 , 0xF0FFFFFF, 0x04000000 },
|
||||
{ GP8_3 , 3 , 0xFF0FFFFF, 0x00400000 },
|
||||
{ GP8_5 , 3 , 0xFFFF0FFF, 0x00004000 },
|
||||
{ GP8_6 , 3 , 0xFFFFF0FF, 0x00000400 },
|
||||
{ GP8_8 , 19, 0xFFFFFF0F, 0x00000080 },
|
||||
{ GP8_9 , 19, 0xFFFFFFF0, 0x00000008 },
|
||||
{ GP8_10, 18, 0x0FFFFFFF, 0x80000000 },
|
||||
{ GP8_11, 18, 0xF0FFFFFF, 0x08000000 },
|
||||
{ GP8_12, 18, 0xFF0FFFFF, 0x00800000 },
|
||||
{ GP8_13, 18, 0xFFF0FFFF, 0x00080000 },
|
||||
{ GP8_14, 18, 0xFFFF0FFF, 0x00008000 },
|
||||
{ GP8_15, 18, 0xFFFFF0FF, 0x00000800 },
|
||||
|
||||
|
||||
{ UART0_TXD, 3, 0xFF0FFFFF, 0x00200000 },
|
||||
{ UART0_RXD, 3, 0xFFF0FFFF, 0x00020000 },
|
||||
|
||||
{ UART1_TXD, 4, 0x0FFFFFFF, 0x20000000 },
|
||||
{ UART1_RXD, 4, 0xF0FFFFFF, 0x02000000 },
|
||||
|
||||
{ SPI0_MOSI, 3, 0xFFFF0FFF, 0x00001000 },
|
||||
{ SPI0_MISO, 3, 0xFFFFF0FF, 0x00000100 },
|
||||
{ SPI0_SCL, 3, 0xFFFFFFF0, 0x00000001 },
|
||||
{ SPI0_CS, 3, 0xF0FFFFFF, 0x01000000 },
|
||||
|
||||
{ SPI1_MOSI, 5, 0xFF0FFFFF, 0x00100000 },
|
||||
{ SPI1_MISO, 5, 0xFFF0FFFF, 0x00010000 },
|
||||
{ SPI1_SCL, 5, 0xFFFFF0FF, 0x00000100 },
|
||||
{ SPI1_CS, 5, 0xFFFF0FFF, 0x00008000 },
|
||||
|
||||
{ EPWM1A, 5, 0xFFFFFFF0, 0x00000002 },
|
||||
{ EPWM1B, 5, 0xFFFFFF0F, 0x00000020 },
|
||||
{ APWM0, 2, 0x0FFFFFFF, 0x20000000 },
|
||||
{ APWM1, 1, 0x0FFFFFFF, 0x40000000 },
|
||||
{ EPWM0B, 3, 0xFFFFFF0F, 0x00000020 },
|
||||
|
||||
{ AXR3, 2, 0xFFF0FFFF, 0x00010000 },
|
||||
{ AXR4, 2, 0xFFFF0FFF, 0x00001000 },
|
||||
|
||||
{-1 }
|
||||
};
|
||||
|
||||
typedef struct gpio_controller *__iomem GPIOC;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int Pin; // GPIO pin number
|
||||
GPIOC pGpio; // GPIO bank base address
|
||||
u32 Mask; // GPIO pin mask
|
||||
}
|
||||
INPIN;
|
||||
|
||||
#define REGUnlock {\
|
||||
iowrite32(0x83E70B13,da8xx_syscfg0_base + 0x38);\
|
||||
iowrite32(0x95A4F1E0,da8xx_syscfg0_base + 0x3C);\
|
||||
}
|
||||
|
||||
#define REGLock {\
|
||||
iowrite32(0x00000000,da8xx_syscfg0_base + 0x38);\
|
||||
iowrite32(0x00000000,da8xx_syscfg0_base + 0x3C);\
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#else
|
||||
|
||||
extern MRM MuxRegMap[];
|
||||
|
||||
#endif /* AM1808_H_ */
|
||||
|
||||
|
1744
brick/kernel/source/bytecodes.h
Normal file
1744
brick/kernel/source/bytecodes.h
Normal file
File diff suppressed because it is too large
Load Diff
81
brick/kernel/source/c_branch.h
Normal file
81
brick/kernel/source/c_branch.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef C_BRANCH_H_
|
||||
#define C_BRANCH_H_
|
||||
|
||||
void cBranchJr(void);
|
||||
|
||||
void cBranchJrFalse(void);
|
||||
|
||||
void cBranchJrTrue(void);
|
||||
|
||||
void cBranchJrNan(void);
|
||||
|
||||
void cBranchJrLt8(void);
|
||||
|
||||
void cBranchJrLt16(void);
|
||||
|
||||
void cBranchJrLt32(void);
|
||||
|
||||
void cBranchJrLtF(void);
|
||||
|
||||
void cBranchJrGt8(void);
|
||||
|
||||
void cBranchJrGt16(void);
|
||||
|
||||
void cBranchJrGt32(void);
|
||||
|
||||
void cBranchJrGtF(void);
|
||||
|
||||
void cBranchJrLtEq8(void);
|
||||
|
||||
void cBranchJrLtEq16(void);
|
||||
|
||||
void cBranchJrLtEq32(void);
|
||||
|
||||
void cBranchJrLtEqF(void);
|
||||
|
||||
void cBranchJrGtEq8(void);
|
||||
|
||||
void cBranchJrGtEq16(void);
|
||||
|
||||
void cBranchJrGtEq32(void);
|
||||
|
||||
void cBranchJrGtEqF(void);
|
||||
|
||||
void cBranchJrEq8(void);
|
||||
|
||||
void cBranchJrEq16(void);
|
||||
|
||||
void cBranchJrEq32(void);
|
||||
|
||||
void cBranchJrEqF(void);
|
||||
|
||||
void cBranchJrNEq8(void);
|
||||
|
||||
void cBranchJrNEq16(void);
|
||||
|
||||
void cBranchJrNEq32(void);
|
||||
|
||||
void cBranchJrNEqF(void);
|
||||
|
||||
#endif /* C_BRANCH_H_ */
|
81
brick/kernel/source/c_compare.h
Normal file
81
brick/kernel/source/c_compare.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef C_COMPARE_H_
|
||||
#define C_COMPARE_H_
|
||||
|
||||
void cCompareLt8(void);
|
||||
|
||||
void cCompareLt16(void);
|
||||
|
||||
void cCompareLt32(void);
|
||||
|
||||
void cCompareLtF(void);
|
||||
|
||||
void cCompareGt8(void);
|
||||
|
||||
void cCompareGt16(void);
|
||||
|
||||
void cCompareGt32(void);
|
||||
|
||||
void cCompareGtF(void);
|
||||
|
||||
void cCompareEq8(void);
|
||||
|
||||
void cCompareEq16(void);
|
||||
|
||||
void cCompareEq32(void);
|
||||
|
||||
void cCompareEqF(void);
|
||||
|
||||
void cCompareNEq8(void);
|
||||
|
||||
void cCompareNEq16(void);
|
||||
|
||||
void cCompareNEq32(void);
|
||||
|
||||
void cCompareNEqF(void);
|
||||
|
||||
void cCompareLtEq8(void);
|
||||
|
||||
void cCompareLtEq16(void);
|
||||
|
||||
void cCompareLtEq32(void);
|
||||
|
||||
void cCompareLtEqF(void);
|
||||
|
||||
void cCompareGtEq8(void);
|
||||
|
||||
void cCompareGtEq16(void);
|
||||
|
||||
void cCompareGtEq32(void);
|
||||
|
||||
void cCompareGtEqF(void);
|
||||
|
||||
void cCompareSelect8(void);
|
||||
|
||||
void cCompareSelect16(void);
|
||||
|
||||
void cCompareSelect32(void);
|
||||
|
||||
void cCompareSelectF(void);
|
||||
|
||||
#endif /* C_COMPARE_H_ */
|
88
brick/kernel/source/c_math.h
Normal file
88
brick/kernel/source/c_math.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef C_MATH_H_
|
||||
#define C_MATH_H_
|
||||
|
||||
#define DegToRad(D) (D * 0.0174532925)
|
||||
|
||||
#define RadToDeg(R) (R * 57.2957795)
|
||||
|
||||
|
||||
void cMathAdd8(void);
|
||||
|
||||
void cMathAdd16(void);
|
||||
|
||||
void cMathAdd32(void);
|
||||
|
||||
void cMathAddF(void);
|
||||
|
||||
void cMathSub8(void);
|
||||
|
||||
void cMathSub16(void);
|
||||
|
||||
void cMathSub32(void);
|
||||
|
||||
void cMathSubF(void);
|
||||
|
||||
void cMathMul8(void);
|
||||
|
||||
void cMathMul16(void);
|
||||
|
||||
void cMathMul32(void);
|
||||
|
||||
void cMathMulF(void);
|
||||
|
||||
void cMathDiv8(void);
|
||||
|
||||
void cMathDiv16(void);
|
||||
|
||||
void cMathDiv32(void);
|
||||
|
||||
void cMathDivF(void);
|
||||
|
||||
void cMathOr8(void);
|
||||
|
||||
void cMathOr16(void);
|
||||
|
||||
void cMathOr32(void);
|
||||
|
||||
void cMathAnd8(void);
|
||||
|
||||
void cMathAnd16(void);
|
||||
|
||||
void cMathAnd32(void);
|
||||
|
||||
void cMathXor8(void);
|
||||
|
||||
void cMathXor16(void);
|
||||
|
||||
void cMathXor32(void);
|
||||
|
||||
void cMathRl8(void);
|
||||
|
||||
void cMathRl16(void);
|
||||
|
||||
void cMathRl32(void);
|
||||
|
||||
void cMath(void);
|
||||
|
||||
#endif /* C_MATH_H_ */
|
76
brick/kernel/source/c_move.h
Normal file
76
brick/kernel/source/c_move.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef C_MOVE_H_
|
||||
#define C_MOVE_H_
|
||||
|
||||
void cMove8to8(void);
|
||||
|
||||
void cMove8to16(void);
|
||||
|
||||
void cMove8to32(void);
|
||||
|
||||
void cMove8toF(void);
|
||||
|
||||
void cMove16to8(void);
|
||||
|
||||
void cMove16to16(void);
|
||||
|
||||
void cMove16to32(void);
|
||||
|
||||
void cMove16toF(void);
|
||||
|
||||
void cMove32to8(void);
|
||||
|
||||
void cMove32to16(void);
|
||||
|
||||
void cMove32to32(void);
|
||||
|
||||
void cMove32toF(void);
|
||||
|
||||
void cMoveFto8(void);
|
||||
|
||||
void cMoveFto16(void);
|
||||
|
||||
void cMoveFto32(void);
|
||||
|
||||
void cMoveFtoF(void);
|
||||
|
||||
void cMoveInitBytes(void);
|
||||
|
||||
void cMoveRead8(void);
|
||||
|
||||
void cMoveRead16(void);
|
||||
|
||||
void cMoveRead32(void);
|
||||
|
||||
void cMoveReadF(void);
|
||||
|
||||
void cMoveWrite8(void);
|
||||
|
||||
void cMoveWrite16(void);
|
||||
|
||||
void cMoveWrite32(void);
|
||||
|
||||
void cMoveWriteF(void);
|
||||
|
||||
|
||||
#endif /* C_MOVE_H_ */
|
38
brick/kernel/source/c_timer.h
Normal file
38
brick/kernel/source/c_timer.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef C_TIMER_H_
|
||||
#define C_TIMER_H_
|
||||
|
||||
#if (HARDWARE != SIMULATION)
|
||||
ULONG cTimerGetuS(void);
|
||||
ULONG cTimerGetmS(void);
|
||||
#endif
|
||||
|
||||
void cTimerWait(void);
|
||||
|
||||
void cTimerReady(void);
|
||||
|
||||
void cTimerRead(void);
|
||||
|
||||
void cTimerReaduS(void);
|
||||
|
||||
#endif /* C_TIMER_H_ */
|
1566
brick/kernel/source/lms2012.h
Executable file
1566
brick/kernel/source/lms2012.h
Executable file
File diff suppressed because it is too large
Load Diff
195
brick/kernel/source/lmstypes.h
Normal file
195
brick/kernel/source/lmstypes.h
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* As a special exception, if other files instantiate templates or use macros or
|
||||
* inline functions from this file, or you compile this file and link it with
|
||||
* other works to produce a work based on this file, this file does not by itself
|
||||
* cause the resulting work to be covered by the GNU General Public License.
|
||||
* However the source code for this file must still be made available in accordance
|
||||
* with section (3) of the GNU General Public License.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LMSTYPES_H_
|
||||
#define LMSTYPES_H_
|
||||
|
||||
// BASIC DATA TYPES
|
||||
|
||||
#ifndef LEGO_SIMULATION
|
||||
|
||||
typedef unsigned char UBYTE; //!< Basic Type used to symbolise 8 bit unsigned values
|
||||
typedef unsigned short UWORD; //!< Basic Type used to symbolise 16 bit unsigned values
|
||||
typedef unsigned int ULONG; //!< Basic Type used to symbolise 32 bit unsigned values
|
||||
|
||||
typedef signed char SBYTE; //!< Basic Type used to symbolise 8 bit signed values
|
||||
typedef signed short SWORD; //!< Basic Type used to symbolise 16 bit signed values
|
||||
typedef signed int SLONG; //!< Basic Type used to symbolise 32 bit signed values
|
||||
|
||||
typedef float FLOAT; //!< Basic Type used to symbolise 32 bit floating point values
|
||||
|
||||
#define LFILE FILE
|
||||
|
||||
#else
|
||||
|
||||
#include <Base/BasicTypes.h>
|
||||
#include <VMCalls.h>
|
||||
|
||||
typedef LEGO::UInt8 UBYTE; //!< Basic Type used to symbolise 8 bit unsigned values
|
||||
typedef LEGO::UInt16 UWORD; //!< Basic Type used to symbolise 16 bit unsigned values
|
||||
typedef unsigned long ULONG; //!< Basic Type used to symbolise 32 bit unsigned values
|
||||
|
||||
|
||||
typedef LEGO::Int8 SBYTE; //!< Basic Type used to symbolise 8 bit signed values
|
||||
typedef LEGO::Int16 SWORD; //!< Basic Type used to symbolise 16 bit signed values
|
||||
typedef LEGO::Int32 SLONG; //!< Basic Type used to symbolise 32 bit signed values
|
||||
|
||||
typedef LEGO::Real32 FLOAT; //!< Basic Type used to symbolise 32 bit floating point values
|
||||
|
||||
#endif
|
||||
|
||||
// VM DATA TYPES
|
||||
|
||||
typedef SBYTE DATA8; //!< VM Type for 1 byte signed value
|
||||
typedef SWORD DATA16; //!< VM Type for 2 byte signed value
|
||||
typedef SLONG DATA32; //!< VM Type for 4 byte signed value
|
||||
typedef FLOAT DATAF; //!< VM Type for 4 byte floating point value
|
||||
|
||||
// VM VARIABLE TYPES
|
||||
|
||||
typedef UBYTE VARDATA; //!< Variable base type
|
||||
typedef UBYTE IMGDATA; //!< Image base type
|
||||
|
||||
typedef UWORD PRGID; //!< Program id type
|
||||
|
||||
typedef UWORD OBJID; //!< Object id type
|
||||
typedef IMGDATA* IP; //!< Instruction pointer type
|
||||
typedef VARDATA* LP; //!< Local variable pointer type
|
||||
typedef VARDATA* GP; //!< global variable pointer type
|
||||
|
||||
typedef ULONG IMINDEX; //!< ImageData index type
|
||||
typedef ULONG GBINDEX; //!< GlobalBytes index type
|
||||
typedef ULONG LBINDEX; //!< LocalBytes index type
|
||||
typedef UWORD TRIGGER; //!< TriggerCount type
|
||||
typedef UBYTE PARS; //!< NoOfParameters type
|
||||
typedef SLONG IMOFFS; //!< ImageData offset type
|
||||
|
||||
typedef DATA16 HANDLER; //!< Memory list index
|
||||
|
||||
|
||||
|
||||
/*! \page imagelayout Image Layout
|
||||
* The image consists of three different components in this fixed order: imageheader, objectheaders and byte codes.
|
||||
*
|
||||
* The imageheader tells something about image version, filesize, no of objectheaders (objects) and no of global variable bytes.
|
||||
*
|
||||
*
|
||||
* Objectheaders contains different informations depending on the nature of the object:
|
||||
*
|
||||
*- The VMTHREAD object (former TBC_TOPVI) \n
|
||||
* - OffsetToInstructions tells were to find the corresponding byte codes (offset from image start) \n
|
||||
* - OwnerObjectId must be zero \n
|
||||
* - TriggerCount is used but must be zero \n
|
||||
* - LocalBytes describes the number of bytes for local variables \n
|
||||
*
|
||||
*- The SUBCALL object (former TBC_VI and TBC_VI_ALIAS) \n
|
||||
* - OffsetToInstructions tells were to find the corresponding byte codes (if alias this is equal to mother object) \n
|
||||
* - OwnerObjectId must be zero \n
|
||||
* - TriggerCount is used and must be one \n
|
||||
* - LocalBytes describes the number of bytes for local variables \n
|
||||
*
|
||||
*- The BLOCK object (former CLUMP) \n
|
||||
* - OffsetToInstructions tells were to find the corresponding byte codes (offset from image start) \n
|
||||
* - OwnerObjectId is equal to object id it belongs to (not equal to zero) \n
|
||||
* - TriggerCount is used to determine how many triggers needed before the BLOCK object is activated \n
|
||||
* - LocalBytes must be zero (locals are defined in the owner object) \n
|
||||
*
|
||||
* Byte codes are described in a different section.
|
||||
*
|
||||
* Little Endian are used (addresses and data are represented with LSB on lowest address and MSB on highest address).
|
||||
*
|
||||
* Offset to instructions is number of bytes from start of image to start of object instructions.
|
||||
*
|
||||
* Index to global variables are byte based and counted from start of globals (zero based).
|
||||
*
|
||||
* Index to local variables are byte based and counted from start of object locals (zero based).
|
||||
*
|
||||
* Object ID's is not zero based - First object (VMTHEAD) is named 1.
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \page imagelayout
|
||||
*
|
||||
* FILE layout (aligned)
|
||||
*
|
||||
*- IMGHEAD (aligned)
|
||||
* - Sign (4 bytes)
|
||||
* - ImageSize (4 bytes)
|
||||
* - VersionInfo (2 bytes)
|
||||
* - NumberOfObjects (2 bytes)
|
||||
* - GlobalBytes (4 bytes)
|
||||
*/
|
||||
|
||||
/*! \struct IMGHEAD
|
||||
* Image header
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
UBYTE Sign[4]; //!< Place holder for the file type identifier
|
||||
IMINDEX ImageSize; //!< Image size
|
||||
UWORD VersionInfo; //!< Version identifier
|
||||
OBJID NumberOfObjects; //!< Total number of objects in image
|
||||
GBINDEX GlobalBytes; //!< Number of bytes to allocate for global variables
|
||||
}
|
||||
IMGHEAD;
|
||||
|
||||
/*! \page imagelayout
|
||||
*
|
||||
*- OBJHEAD (aligned)
|
||||
* - OffsetToInstructions (4 bytes)
|
||||
* - OwnerObjectId (2 bytes)
|
||||
* - TriggerCount (2 bytes)
|
||||
* - LocalBytes (4 bytes)
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \struct OBJHEAD
|
||||
* Object header used for all types of objects (VMTHREAD, SUBCALL, BLOCK and ALIAS)
|
||||
*/
|
||||
typedef struct // Object header
|
||||
{
|
||||
IP OffsetToInstructions; //!< Offset to instructions from image start
|
||||
OBJID OwnerObjectId; //!< Used by BLOCK's to hold the owner id
|
||||
TRIGGER TriggerCount; //!< Used to determine how many triggers needed before the BLOCK object is activated
|
||||
LBINDEX LocalBytes; //!< Number of bytes to allocate for local variables
|
||||
}
|
||||
OBJHEAD;
|
||||
|
||||
|
||||
/*! \struct LABEL
|
||||
* Label data hold information used for labels
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
IMINDEX Addr; //!< Offset to breakpoint address from image start
|
||||
}
|
||||
LABEL;
|
||||
|
||||
|
||||
#endif /* LMSTYPES_H_ */
|
56
brick/kernel/source/validate.h
Normal file
56
brick/kernel/source/validate.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef VALIDATE_H_
|
||||
#define VALIDATE_H_
|
||||
|
||||
RESULT cValidateInit(void);
|
||||
|
||||
RESULT cValidateExit(void);
|
||||
|
||||
RESULT cValidateDisassemble(IP pI,IMINDEX *pIndex,LABEL *pLabel);
|
||||
|
||||
RESULT cValidateProgram(PRGID PrgId,IP pI,LABEL *pLabel,DATA8 Disassemble);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//*****************************************************************************
|
||||
// Validate Global variables
|
||||
//*****************************************************************************
|
||||
|
||||
int Row;
|
||||
IMINDEX ValidateErrorIndex;
|
||||
}
|
||||
VALIDATE_GLOBALS;
|
||||
|
||||
#ifndef LEGO_SIMULATION
|
||||
extern VALIDATE_GLOBALS ValidateInstance;
|
||||
#else
|
||||
extern VALIDATE_GLOBALS * gValidateInstance;
|
||||
#define ValidateInstance (*gValidateInstance)
|
||||
|
||||
void setValidateInstance(VALIDATE_GLOBALS * _Instance);
|
||||
VALIDATE_GLOBALS * getValidateInstance();
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* VALIDATE_H_ */
|
778
brick/kernel/storage_common.c
Normal file
778
brick/kernel/storage_common.c
Normal file
@ -0,0 +1,778 @@
|
||||
/*
|
||||
* storage_common.c -- Common definitions for mass storage functionality
|
||||
*
|
||||
* Copyright (C) 2003-2008 Alan Stern
|
||||
* Copyeight (C) 2009 Samsung Electronics
|
||||
* Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This file requires the following identifiers used in USB strings to
|
||||
* be defined (each of type pointer to char):
|
||||
* - fsg_string_manufacturer -- name of the manufacturer
|
||||
* - fsg_string_product -- name of the product
|
||||
* - fsg_string_serial -- product's serial
|
||||
* - fsg_string_config -- name of the configuration
|
||||
* - fsg_string_interface -- name of the interface
|
||||
* The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS
|
||||
* macro is defined prior to including this file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and
|
||||
* fsg_hs_intr_in_desc objects as well as
|
||||
* FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES
|
||||
* macros are not defined.
|
||||
*
|
||||
* When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER,
|
||||
* FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not
|
||||
* defined (as well as corresponding entries in string tables are
|
||||
* missing) and FSG_STRING_INTERFACE has value of zero.
|
||||
*
|
||||
* When FSG_NO_OTG is defined fsg_otg_desc won't be defined.
|
||||
*/
|
||||
|
||||
/*
|
||||
* When FSG_BUFFHD_STATIC_BUFFER is defined when this file is included
|
||||
* the fsg_buffhd structure's buf field will be an array of FSG_BUFLEN
|
||||
* characters rather then a pointer to void.
|
||||
*/
|
||||
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
|
||||
/* Thanks to NetChip Technologies for donating this product ID.
|
||||
*
|
||||
* DO NOT REUSE THESE IDs with any other driver!! Ever!!
|
||||
* Instead: allocate your own, using normal USB-IF procedures. */
|
||||
#define FSG_VENDOR_ID 0x0525 /* NetChip */
|
||||
#define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef DEBUG
|
||||
#undef VERBOSE_DEBUG
|
||||
#undef DUMP_MSGS
|
||||
#endif /* !DEBUG */
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
#define VLDBG LDBG
|
||||
#else
|
||||
#define VLDBG(lun, fmt, args...) do { } while (0)
|
||||
#endif /* VERBOSE_DEBUG */
|
||||
|
||||
#define LDBG(lun, fmt, args...) dev_dbg (&(lun)->dev, fmt, ## args)
|
||||
#define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args)
|
||||
#define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args)
|
||||
#define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args)
|
||||
|
||||
/* Keep those macros in sync with thos in
|
||||
* include/linux/ubs/composite.h or else GCC will complain. If they
|
||||
* are identical (the same names of arguments, white spaces in the
|
||||
* same places) GCC will allow redefinition otherwise (even if some
|
||||
* white space is removed or added) warning will be issued. No
|
||||
* checking if those symbols is defined is performed because warning
|
||||
* is desired when those macros were defined by someone else to mean
|
||||
* something else. */
|
||||
#define DBG(d, fmt, args...) dev_dbg(&(d)->gadget->dev , fmt , ## args)
|
||||
#define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev , fmt , ## args)
|
||||
#define ERROR(d, fmt, args...) dev_err(&(d)->gadget->dev , fmt , ## args)
|
||||
#define WARNING(d, fmt, args...) dev_warn(&(d)->gadget->dev , fmt , ## args)
|
||||
#define INFO(d, fmt, args...) dev_info(&(d)->gadget->dev , fmt , ## args)
|
||||
|
||||
|
||||
|
||||
#ifdef DUMP_MSGS
|
||||
|
||||
# define dump_msg(fsg, /* const char * */ label, \
|
||||
/* const u8 * */ buf, /* unsigned */ length) do { \
|
||||
if (length < 512) { \
|
||||
DBG(fsg, "%s, length %u:\n", label, length); \
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \
|
||||
16, 1, buf, length, 0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
# define dump_cdb(fsg) do { } while (0)
|
||||
|
||||
#else
|
||||
|
||||
# define dump_msg(fsg, /* const char * */ label, \
|
||||
/* const u8 * */ buf, /* unsigned */ length) do { } while (0)
|
||||
|
||||
# ifdef VERBOSE_DEBUG
|
||||
|
||||
# define dump_cdb(fsg) \
|
||||
print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE, \
|
||||
16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0) \
|
||||
|
||||
# else
|
||||
|
||||
# define dump_cdb(fsg) do { } while (0)
|
||||
|
||||
# endif /* VERBOSE_DEBUG */
|
||||
|
||||
#endif /* DUMP_MSGS */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* SCSI device types */
|
||||
#define TYPE_DISK 0x00
|
||||
#define TYPE_CDROM 0x05
|
||||
|
||||
/* USB protocol value = the transport method */
|
||||
#define USB_PR_CBI 0x00 /* Control/Bulk/Interrupt */
|
||||
#define USB_PR_CB 0x01 /* Control/Bulk w/o interrupt */
|
||||
#define USB_PR_BULK 0x50 /* Bulk-only */
|
||||
|
||||
/* USB subclass value = the protocol encapsulation */
|
||||
#define USB_SC_RBC 0x01 /* Reduced Block Commands (flash) */
|
||||
#define USB_SC_8020 0x02 /* SFF-8020i, MMC-2, ATAPI (CD-ROM) */
|
||||
#define USB_SC_QIC 0x03 /* QIC-157 (tape) */
|
||||
#define USB_SC_UFI 0x04 /* UFI (floppy) */
|
||||
#define USB_SC_8070 0x05 /* SFF-8070i (removable) */
|
||||
#define USB_SC_SCSI 0x06 /* Transparent SCSI */
|
||||
|
||||
/* Bulk-only data structures */
|
||||
|
||||
/* Command Block Wrapper */
|
||||
struct fsg_bulk_cb_wrap {
|
||||
__le32 Signature; /* Contains 'USBC' */
|
||||
u32 Tag; /* Unique per command id */
|
||||
__le32 DataTransferLength; /* Size of the data */
|
||||
u8 Flags; /* Direction in bit 7 */
|
||||
u8 Lun; /* LUN (normally 0) */
|
||||
u8 Length; /* Of the CDB, <= MAX_COMMAND_SIZE */
|
||||
u8 CDB[16]; /* Command Data Block */
|
||||
};
|
||||
|
||||
#define USB_BULK_CB_WRAP_LEN 31
|
||||
#define USB_BULK_CB_SIG 0x43425355 /* Spells out USBC */
|
||||
#define USB_BULK_IN_FLAG 0x80
|
||||
|
||||
/* Command Status Wrapper */
|
||||
struct bulk_cs_wrap {
|
||||
__le32 Signature; /* Should = 'USBS' */
|
||||
u32 Tag; /* Same as original command */
|
||||
__le32 Residue; /* Amount not transferred */
|
||||
u8 Status; /* See below */
|
||||
};
|
||||
|
||||
#define USB_BULK_CS_WRAP_LEN 13
|
||||
#define USB_BULK_CS_SIG 0x53425355 /* Spells out 'USBS' */
|
||||
#define USB_STATUS_PASS 0
|
||||
#define USB_STATUS_FAIL 1
|
||||
#define USB_STATUS_PHASE_ERROR 2
|
||||
|
||||
/* Bulk-only class specific requests */
|
||||
#define USB_BULK_RESET_REQUEST 0xff
|
||||
#define USB_BULK_GET_MAX_LUN_REQUEST 0xfe
|
||||
|
||||
|
||||
/* CBI Interrupt data structure */
|
||||
struct interrupt_data {
|
||||
u8 bType;
|
||||
u8 bValue;
|
||||
};
|
||||
|
||||
#define CBI_INTERRUPT_DATA_LEN 2
|
||||
|
||||
/* CBI Accept Device-Specific Command request */
|
||||
#define USB_CBI_ADSC_REQUEST 0x00
|
||||
|
||||
|
||||
/* Length of a SCSI Command Data Block */
|
||||
#define MAX_COMMAND_SIZE 16
|
||||
|
||||
/* SCSI commands that we recognize */
|
||||
#define SC_FORMAT_UNIT 0x04
|
||||
#define SC_INQUIRY 0x12
|
||||
#define SC_MODE_SELECT_6 0x15
|
||||
#define SC_MODE_SELECT_10 0x55
|
||||
#define SC_MODE_SENSE_6 0x1a
|
||||
#define SC_MODE_SENSE_10 0x5a
|
||||
#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
|
||||
#define SC_READ_6 0x08
|
||||
#define SC_READ_10 0x28
|
||||
#define SC_READ_12 0xa8
|
||||
#define SC_READ_CAPACITY 0x25
|
||||
#define SC_READ_FORMAT_CAPACITIES 0x23
|
||||
#define SC_READ_HEADER 0x44
|
||||
#define SC_READ_TOC 0x43
|
||||
#define SC_RELEASE 0x17
|
||||
#define SC_REQUEST_SENSE 0x03
|
||||
#define SC_RESERVE 0x16
|
||||
#define SC_SEND_DIAGNOSTIC 0x1d
|
||||
#define SC_START_STOP_UNIT 0x1b
|
||||
#define SC_SYNCHRONIZE_CACHE 0x35
|
||||
#define SC_TEST_UNIT_READY 0x00
|
||||
#define SC_VERIFY 0x2f
|
||||
#define SC_WRITE_6 0x0a
|
||||
#define SC_WRITE_10 0x2a
|
||||
#define SC_WRITE_12 0xaa
|
||||
|
||||
/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
|
||||
#define SS_NO_SENSE 0
|
||||
#define SS_COMMUNICATION_FAILURE 0x040800
|
||||
#define SS_INVALID_COMMAND 0x052000
|
||||
#define SS_INVALID_FIELD_IN_CDB 0x052400
|
||||
#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100
|
||||
#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500
|
||||
#define SS_MEDIUM_NOT_PRESENT 0x023a00
|
||||
#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302
|
||||
#define SS_NOT_READY_TO_READY_TRANSITION 0x062800
|
||||
#define SS_RESET_OCCURRED 0x062900
|
||||
#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900
|
||||
#define SS_UNRECOVERED_READ_ERROR 0x031100
|
||||
#define SS_WRITE_ERROR 0x030c02
|
||||
#define SS_WRITE_PROTECTED 0x072700
|
||||
|
||||
#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */
|
||||
#define ASC(x) ((u8) ((x) >> 8))
|
||||
#define ASCQ(x) ((u8) (x))
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
struct fsg_lun {
|
||||
struct file *filp;
|
||||
loff_t file_length;
|
||||
loff_t num_sectors;
|
||||
|
||||
unsigned int initially_ro:1;
|
||||
unsigned int ro:1;
|
||||
unsigned int removable:1;
|
||||
unsigned int cdrom:1;
|
||||
unsigned int prevent_medium_removal:1;
|
||||
unsigned int registered:1;
|
||||
unsigned int info_valid:1;
|
||||
|
||||
u32 sense_data;
|
||||
u32 sense_data_info;
|
||||
u32 unit_attention_data;
|
||||
|
||||
struct device dev;
|
||||
};
|
||||
|
||||
#define fsg_lun_is_open(curlun) ((curlun)->filp != NULL)
|
||||
|
||||
static struct fsg_lun *fsg_lun_from_dev(struct device *dev)
|
||||
{
|
||||
return container_of(dev, struct fsg_lun, dev);
|
||||
}
|
||||
|
||||
|
||||
/* Big enough to hold our biggest descriptor */
|
||||
#define EP0_BUFSIZE 256
|
||||
#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */
|
||||
|
||||
/* Number of buffers we will use. 2 is enough for double-buffering */
|
||||
#define FSG_NUM_BUFFERS 2
|
||||
|
||||
/* Default size of buffer length. */
|
||||
#define FSG_BUFLEN ((u32)16384)
|
||||
|
||||
/* Maximal number of LUNs supported in mass storage function */
|
||||
#define FSG_MAX_LUNS 8
|
||||
|
||||
enum fsg_buffer_state {
|
||||
BUF_STATE_EMPTY = 0,
|
||||
BUF_STATE_FULL,
|
||||
BUF_STATE_BUSY
|
||||
};
|
||||
|
||||
struct fsg_buffhd {
|
||||
#ifdef FSG_BUFFHD_STATIC_BUFFER
|
||||
char buf[FSG_BUFLEN];
|
||||
#else
|
||||
void *buf;
|
||||
#endif
|
||||
enum fsg_buffer_state state;
|
||||
struct fsg_buffhd *next;
|
||||
|
||||
/* The NetChip 2280 is faster, and handles some protocol faults
|
||||
* better, if we don't submit any short bulk-out read requests.
|
||||
* So we will record the intended request length here. */
|
||||
unsigned int bulk_out_intended_length;
|
||||
|
||||
struct usb_request *inreq;
|
||||
int inreq_busy;
|
||||
struct usb_request *outreq;
|
||||
int outreq_busy;
|
||||
};
|
||||
|
||||
enum fsg_state {
|
||||
/* This one isn't used anywhere */
|
||||
FSG_STATE_COMMAND_PHASE = -10,
|
||||
FSG_STATE_DATA_PHASE,
|
||||
FSG_STATE_STATUS_PHASE,
|
||||
|
||||
FSG_STATE_IDLE = 0,
|
||||
FSG_STATE_ABORT_BULK_OUT,
|
||||
FSG_STATE_RESET,
|
||||
FSG_STATE_INTERFACE_CHANGE,
|
||||
FSG_STATE_CONFIG_CHANGE,
|
||||
FSG_STATE_DISCONNECT,
|
||||
FSG_STATE_EXIT,
|
||||
FSG_STATE_TERMINATED
|
||||
};
|
||||
|
||||
enum data_direction {
|
||||
DATA_DIR_UNKNOWN = 0,
|
||||
DATA_DIR_FROM_HOST,
|
||||
DATA_DIR_TO_HOST,
|
||||
DATA_DIR_NONE
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static inline u32 get_unaligned_be24(u8 *buf)
|
||||
{
|
||||
return 0xffffff & (u32) get_unaligned_be32(buf - 1);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
enum {
|
||||
#ifndef FSG_NO_DEVICE_STRINGS
|
||||
FSG_STRING_MANUFACTURER = 1,
|
||||
FSG_STRING_PRODUCT,
|
||||
FSG_STRING_SERIAL,
|
||||
FSG_STRING_CONFIG,
|
||||
#endif
|
||||
FSG_STRING_INTERFACE
|
||||
};
|
||||
|
||||
|
||||
#ifndef FSG_NO_OTG
|
||||
static struct usb_otg_descriptor
|
||||
fsg_otg_desc = {
|
||||
.bLength = sizeof fsg_otg_desc,
|
||||
.bDescriptorType = USB_DT_OTG,
|
||||
|
||||
.bmAttributes = USB_OTG_SRP,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* There is only one interface. */
|
||||
|
||||
static struct usb_interface_descriptor
|
||||
fsg_intf_desc = {
|
||||
.bLength = sizeof fsg_intf_desc,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
|
||||
.bNumEndpoints = 2, /* Adjusted during fsg_bind() */
|
||||
.bInterfaceClass = USB_CLASS_MASS_STORAGE,
|
||||
.bInterfaceSubClass = USB_SC_SCSI, /* Adjusted during fsg_bind() */
|
||||
.bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */
|
||||
.iInterface = FSG_STRING_INTERFACE,
|
||||
};
|
||||
|
||||
/* Three full-speed endpoint descriptors: bulk-in, bulk-out,
|
||||
* and interrupt-in. */
|
||||
|
||||
static struct usb_endpoint_descriptor
|
||||
fsg_fs_bulk_in_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||
/* wMaxPacketSize set by autoconfiguration */
|
||||
};
|
||||
|
||||
static struct usb_endpoint_descriptor
|
||||
fsg_fs_bulk_out_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
.bEndpointAddress = USB_DIR_OUT,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||
/* wMaxPacketSize set by autoconfiguration */
|
||||
};
|
||||
|
||||
#ifndef FSG_NO_INTR_EP
|
||||
|
||||
static struct usb_endpoint_descriptor
|
||||
fsg_fs_intr_in_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(2),
|
||||
.bInterval = 32, /* frames -> 32 ms */
|
||||
};
|
||||
|
||||
#ifndef FSG_NO_OTG
|
||||
# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 2
|
||||
#else
|
||||
# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
static struct usb_descriptor_header *fsg_fs_function[] = {
|
||||
#ifndef FSG_NO_OTG
|
||||
(struct usb_descriptor_header *) &fsg_otg_desc,
|
||||
#endif
|
||||
(struct usb_descriptor_header *) &fsg_intf_desc,
|
||||
(struct usb_descriptor_header *) &fsg_fs_bulk_in_desc,
|
||||
(struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
|
||||
#ifndef FSG_NO_INTR_EP
|
||||
(struct usb_descriptor_header *) &fsg_fs_intr_in_desc,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* USB 2.0 devices need to expose both high speed and full speed
|
||||
* descriptors, unless they only run at full speed.
|
||||
*
|
||||
* That means alternate endpoint descriptors (bigger packets)
|
||||
* and a "device qualifier" ... plus more construction options
|
||||
* for the config descriptor.
|
||||
*/
|
||||
static struct usb_endpoint_descriptor
|
||||
fsg_hs_bulk_in_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
/* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
|
||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||
.wMaxPacketSize = cpu_to_le16(512),
|
||||
};
|
||||
|
||||
static struct usb_endpoint_descriptor
|
||||
fsg_hs_bulk_out_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
/* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
|
||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||
.wMaxPacketSize = cpu_to_le16(512),
|
||||
.bInterval = 1, /* NAK every 1 uframe */
|
||||
};
|
||||
|
||||
#ifndef FSG_NO_INTR_EP
|
||||
|
||||
static struct usb_endpoint_descriptor
|
||||
fsg_hs_intr_in_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
|
||||
/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(2),
|
||||
.bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */
|
||||
};
|
||||
|
||||
#ifndef FSG_NO_OTG
|
||||
# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 2
|
||||
#else
|
||||
# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
static struct usb_descriptor_header *fsg_hs_function[] = {
|
||||
#ifndef FSG_NO_OTG
|
||||
(struct usb_descriptor_header *) &fsg_otg_desc,
|
||||
#endif
|
||||
(struct usb_descriptor_header *) &fsg_intf_desc,
|
||||
(struct usb_descriptor_header *) &fsg_hs_bulk_in_desc,
|
||||
(struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
|
||||
#ifndef FSG_NO_INTR_EP
|
||||
(struct usb_descriptor_header *) &fsg_hs_intr_in_desc,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* Maxpacket and other transfer characteristics vary by speed. */
|
||||
static struct usb_endpoint_descriptor *
|
||||
fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
|
||||
struct usb_endpoint_descriptor *hs)
|
||||
{
|
||||
if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
|
||||
return hs;
|
||||
return fs;
|
||||
}
|
||||
|
||||
|
||||
/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
|
||||
static struct usb_string fsg_strings[] = {
|
||||
#ifndef FSG_NO_DEVICE_STRINGS
|
||||
{FSG_STRING_MANUFACTURER, fsg_string_manufacturer},
|
||||
{FSG_STRING_PRODUCT, fsg_string_product},
|
||||
{FSG_STRING_SERIAL, fsg_string_serial},
|
||||
{FSG_STRING_CONFIG, fsg_string_config},
|
||||
#endif
|
||||
{FSG_STRING_INTERFACE, fsg_string_interface},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings fsg_stringtab = {
|
||||
.language = 0x0409, /* en-us */
|
||||
.strings = fsg_strings,
|
||||
};
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* If the next two routines are called while the gadget is registered,
|
||||
* the caller must own fsg->filesem for writing. */
|
||||
|
||||
static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
|
||||
{
|
||||
int ro;
|
||||
struct file *filp = NULL;
|
||||
int rc = -EINVAL;
|
||||
struct inode *inode = NULL;
|
||||
loff_t size;
|
||||
loff_t num_sectors;
|
||||
loff_t min_sectors;
|
||||
|
||||
/* R/W if we can, R/O if we must */
|
||||
ro = curlun->initially_ro;
|
||||
if (!ro) {
|
||||
filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
|
||||
if (-EROFS == PTR_ERR(filp))
|
||||
ro = 1;
|
||||
}
|
||||
if (ro)
|
||||
filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0);
|
||||
if (IS_ERR(filp)) {
|
||||
LINFO(curlun, "unable to open backing file: %s\n", filename);
|
||||
return PTR_ERR(filp);
|
||||
}
|
||||
|
||||
if (!(filp->f_mode & FMODE_WRITE))
|
||||
ro = 1;
|
||||
|
||||
if (filp->f_path.dentry)
|
||||
inode = filp->f_path.dentry->d_inode;
|
||||
if (inode && S_ISBLK(inode->i_mode)) {
|
||||
if (bdev_read_only(inode->i_bdev))
|
||||
ro = 1;
|
||||
} else if (!inode || !S_ISREG(inode->i_mode)) {
|
||||
LINFO(curlun, "invalid file type: %s\n", filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If we can't read the file, it's no good.
|
||||
* If we can't write the file, use it read-only. */
|
||||
if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) {
|
||||
LINFO(curlun, "file not readable: %s\n", filename);
|
||||
goto out;
|
||||
}
|
||||
if (!(filp->f_op->write || filp->f_op->aio_write))
|
||||
ro = 1;
|
||||
|
||||
size = i_size_read(inode->i_mapping->host);
|
||||
if (size < 0) {
|
||||
LINFO(curlun, "unable to find file size: %s\n", filename);
|
||||
rc = (int) size;
|
||||
goto out;
|
||||
}
|
||||
num_sectors = size >> 9; /* File size in 512-byte blocks */
|
||||
min_sectors = 1;
|
||||
if (curlun->cdrom) {
|
||||
num_sectors &= ~3; /* Reduce to a multiple of 2048 */
|
||||
min_sectors = 300*4; /* Smallest track is 300 frames */
|
||||
if (num_sectors >= 256*60*75*4) {
|
||||
num_sectors = (256*60*75 - 1) * 4;
|
||||
LINFO(curlun, "file too big: %s\n", filename);
|
||||
LINFO(curlun, "using only first %d blocks\n",
|
||||
(int) num_sectors);
|
||||
}
|
||||
}
|
||||
if (num_sectors < min_sectors) {
|
||||
LINFO(curlun, "file too small: %s\n", filename);
|
||||
rc = -ETOOSMALL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
get_file(filp);
|
||||
curlun->ro = ro;
|
||||
curlun->filp = filp;
|
||||
curlun->file_length = size;
|
||||
curlun->num_sectors = num_sectors;
|
||||
LDBG(curlun, "open backing file: %s\n", filename);
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
filp_close(filp, current->files);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static void fsg_lun_close(struct fsg_lun *curlun)
|
||||
{
|
||||
if (curlun->filp) {
|
||||
LDBG(curlun, "close backing file\n");
|
||||
fput(curlun->filp);
|
||||
curlun->filp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* Sync the file data, don't bother with the metadata.
|
||||
* This code was copied from fs/buffer.c:sys_fdatasync(). */
|
||||
static int fsg_lun_fsync_sub(struct fsg_lun *curlun)
|
||||
{
|
||||
struct file *filp = curlun->filp;
|
||||
|
||||
if (curlun->ro || !filp)
|
||||
return 0;
|
||||
return vfs_fsync(filp, filp->f_path.dentry, 1);
|
||||
}
|
||||
|
||||
static void store_cdrom_address(u8 *dest, int msf, u32 addr)
|
||||
{
|
||||
if (msf) {
|
||||
/* Convert to Minutes-Seconds-Frames */
|
||||
addr >>= 2; /* Convert to 2048-byte frames */
|
||||
addr += 2*75; /* Lead-in occupies 2 seconds */
|
||||
dest[3] = addr % 75; /* Frames */
|
||||
addr /= 75;
|
||||
dest[2] = addr % 60; /* Seconds */
|
||||
addr /= 60;
|
||||
dest[1] = addr; /* Minutes */
|
||||
dest[0] = 0; /* Reserved */
|
||||
} else {
|
||||
/* Absolute sector */
|
||||
put_unaligned_be32(addr, dest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct fsg_lun *curlun = fsg_lun_from_dev(dev);
|
||||
|
||||
return sprintf(buf, "%d\n", fsg_lun_is_open(curlun)
|
||||
? curlun->ro
|
||||
: curlun->initially_ro);
|
||||
}
|
||||
|
||||
static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct fsg_lun *curlun = fsg_lun_from_dev(dev);
|
||||
struct rw_semaphore *filesem = dev_get_drvdata(dev);
|
||||
char *p;
|
||||
ssize_t rc;
|
||||
|
||||
down_read(filesem);
|
||||
if (fsg_lun_is_open(curlun)) { /* Get the complete pathname */
|
||||
p = d_path(&curlun->filp->f_path, buf, PAGE_SIZE - 1);
|
||||
if (IS_ERR(p))
|
||||
rc = PTR_ERR(p);
|
||||
else {
|
||||
rc = strlen(p);
|
||||
memmove(buf, p, rc);
|
||||
buf[rc] = '\n'; /* Add a newline */
|
||||
buf[++rc] = 0;
|
||||
}
|
||||
} else { /* No file, return 0 bytes */
|
||||
*buf = 0;
|
||||
rc = 0;
|
||||
}
|
||||
up_read(filesem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
ssize_t rc = count;
|
||||
struct fsg_lun *curlun = fsg_lun_from_dev(dev);
|
||||
struct rw_semaphore *filesem = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
if (sscanf(buf, "%d", &i) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* Allow the write-enable status to change only while the backing file
|
||||
* is closed. */
|
||||
down_read(filesem);
|
||||
if (fsg_lun_is_open(curlun)) {
|
||||
LDBG(curlun, "read-only status change prevented\n");
|
||||
rc = -EBUSY;
|
||||
} else {
|
||||
curlun->ro = !!i;
|
||||
curlun->initially_ro = !!i;
|
||||
LDBG(curlun, "read-only status set to %d\n", curlun->ro);
|
||||
}
|
||||
up_read(filesem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fsg_lun *curlun = fsg_lun_from_dev(dev);
|
||||
struct rw_semaphore *filesem = dev_get_drvdata(dev);
|
||||
int rc = 0;
|
||||
|
||||
if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) {
|
||||
LDBG(curlun, "eject attempt prevented\n");
|
||||
return -EBUSY; /* "Door is locked" */
|
||||
}
|
||||
|
||||
/* Remove a trailing newline */
|
||||
if (count > 0 && buf[count-1] == '\n')
|
||||
((char *) buf)[count-1] = 0; /* Ugh! */
|
||||
|
||||
/* Eject current medium */
|
||||
down_write(filesem);
|
||||
if (fsg_lun_is_open(curlun)) {
|
||||
fsg_lun_close(curlun);
|
||||
curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
|
||||
}
|
||||
|
||||
/* Load new medium */
|
||||
if (count > 0 && buf[0]) {
|
||||
rc = fsg_lun_open(curlun, buf);
|
||||
if (rc == 0)
|
||||
curlun->unit_attention_data =
|
||||
SS_NOT_READY_TO_READY_TRANSITION;
|
||||
}
|
||||
up_write(filesem);
|
||||
return (rc < 0 ? rc : count);
|
||||
}
|
726
brick/kernel/usb_function.c
Normal file
726
brick/kernel/usb_function.c
Normal file
@ -0,0 +1,726 @@
|
||||
/*
|
||||
* LEGO® MINDSTORMS EV3
|
||||
*
|
||||
* Copyright (C) 2010-2013 The LEGO Group
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This UsbFunction file is based on and inheritated from
|
||||
* the original file (f_sourcesink.c) and work done by
|
||||
* David Brownell
|
||||
*
|
||||
* >> f_sourcesink.c - USB peripheral source/sink configuration driver <<
|
||||
*
|
||||
* >> Copyright (C) 2003-2008 David Brownell <<
|
||||
* >> Copyright (C) 2008 by Nokia Corporation <<
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* HID IN/OUT Interrupt transfer FUNCTION ...
|
||||
*
|
||||
*/
|
||||
|
||||
struct f_rudolf {
|
||||
struct usb_function function;
|
||||
|
||||
struct usb_ep *in_ep;
|
||||
struct usb_ep *out_ep;
|
||||
};
|
||||
|
||||
enum // Used for signaling the IN stuff USB-state
|
||||
{ // Data from the Brick to the HOST
|
||||
USB_DATA_IDLE, //
|
||||
USB_DATA_BUSY, // Ongoing USB request
|
||||
USB_DATA_PENDING, // Data ready for X-fer, but USB busy
|
||||
USB_DATA_READY, // Initial setting
|
||||
};
|
||||
|
||||
int input_state = USB_DATA_IDLE;
|
||||
struct usb_ep *save_in_ep;
|
||||
struct usb_request *save_in_req;
|
||||
|
||||
#ifndef PCASM
|
||||
static inline struct f_rudolf *func_to_rudolf(struct usb_function *f)
|
||||
{
|
||||
return container_of(f, struct f_rudolf, function);
|
||||
}
|
||||
#else
|
||||
// Keep Eclipse happy
|
||||
#endif
|
||||
|
||||
static struct usb_interface_descriptor rudolf_intf = {
|
||||
.bLength = sizeof rudolf_intf,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 2, // Just plain in and out
|
||||
.bInterfaceClass = USB_CLASS_HID, // We go for NONE custom-driver
|
||||
.bInterfaceSubClass = 0,
|
||||
.bInterfaceProtocol = 0,
|
||||
/* .iInterface = DYNAMIC */
|
||||
};
|
||||
|
||||
static struct hid_descriptor hs_hid_rudolf_desc = {
|
||||
.bLength = sizeof hs_hid_rudolf_desc,
|
||||
.bDescriptorType = HID_DT_HID,
|
||||
.bcdHID = cpu_to_le16(0x0110),
|
||||
.bCountryCode = 0x00,
|
||||
.bNumDescriptors = 0x01, // "The one and only"
|
||||
.desc[0].bDescriptorType = 0x22, // Report Descriptor Type - 0x22 = HID
|
||||
.desc[0].wDescriptorLength = sizeof hs_hid_report_descriptor,
|
||||
/*.desc[0].bDescriptorType = DYNAMIC */
|
||||
/*.desc[0].wDescriptorLenght= DYNAMIC */
|
||||
};
|
||||
|
||||
static struct hid_descriptor fs_hid_rudolf_desc = {
|
||||
.bLength = sizeof fs_hid_rudolf_desc,
|
||||
.bDescriptorType = HID_DT_HID,
|
||||
.bcdHID = cpu_to_le16(0x0110),
|
||||
.bCountryCode = 0x00,
|
||||
.bNumDescriptors = 0x01, // "The one and only"
|
||||
.desc[0].bDescriptorType = 0x22, // Report Descriptor Type - 0x22 = HID
|
||||
.desc[0].wDescriptorLength = sizeof fs_hid_report_descriptor,
|
||||
|
||||
};
|
||||
|
||||
/* full speed support: */
|
||||
|
||||
static struct usb_endpoint_descriptor rudolf_out_fs_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = USB_DIR_OUT,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(64),
|
||||
.bInterval = 1, /* 1 = 1 mSec POLL rate for FS */
|
||||
};
|
||||
|
||||
static struct usb_endpoint_descriptor rudolf_in_fs_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(64),
|
||||
.bInterval = 1, /* 1 = 1 mSec POLL rate for FS */
|
||||
};
|
||||
|
||||
/* high speed support: */
|
||||
|
||||
static struct usb_endpoint_descriptor rudolf_in_hs_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = USB_DIR_IN,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(1024),
|
||||
.bInterval = 4, /* Calculated as :
|
||||
* 2^(value-1) * 125uS
|
||||
* i.e. value 1: 2^(1-1) * 125 uSec = 125 uSec
|
||||
* - 4: 2^(4-1) * 125 uSec = 1 mSec
|
||||
*/
|
||||
};
|
||||
|
||||
static struct usb_endpoint_descriptor rudolf_out_hs_desc = {
|
||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||
.bDescriptorType = USB_DT_ENDPOINT,
|
||||
.bEndpointAddress = USB_DIR_OUT,
|
||||
.bmAttributes = USB_ENDPOINT_XFER_INT,
|
||||
.wMaxPacketSize = cpu_to_le16(1024),
|
||||
.bInterval = 4, /* Calculated as :
|
||||
* 2^(value-1) * 125uS
|
||||
* i.e. value 1: 2^(1-1) * 125 uSec = 125 uSec
|
||||
* - 4: 2^(4-1) * 125 uSec = 1 mSec
|
||||
*/
|
||||
};
|
||||
|
||||
static struct usb_descriptor_header *hs_rudolf_descs[] = {
|
||||
(struct usb_descriptor_header *) &rudolf_intf,
|
||||
(struct usb_descriptor_header *) &hs_hid_rudolf_desc,
|
||||
(struct usb_descriptor_header *) &rudolf_in_hs_desc,
|
||||
(struct usb_descriptor_header *) &rudolf_out_hs_desc,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct usb_descriptor_header *fs_rudolf_descs[] = {
|
||||
(struct usb_descriptor_header *) &rudolf_intf,
|
||||
(struct usb_descriptor_header *) &fs_hid_rudolf_desc,
|
||||
(struct usb_descriptor_header *) &rudolf_in_fs_desc,
|
||||
(struct usb_descriptor_header *) &rudolf_out_fs_desc,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* function-specific strings: */
|
||||
|
||||
static struct usb_string strings_rudolf[] = {
|
||||
[0].s = "Xfer data to and from EV3 brick",
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings stringtab_rudolf = {
|
||||
.language = 0x0409, /* en-us */
|
||||
.strings = strings_rudolf,
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings *rudolf_strings[] = {
|
||||
&stringtab_rudolf,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
f_rudolf_bind(struct usb_configuration *c, struct usb_function *f)
|
||||
{
|
||||
struct usb_composite_dev *cdev = c->cdev;
|
||||
struct f_rudolf *rudolf = func_to_rudolf(f);
|
||||
int id;
|
||||
|
||||
/* allocate interface ID(s) */
|
||||
id = usb_interface_id(c, f);
|
||||
if (id < 0)
|
||||
return id;
|
||||
rudolf_intf.bInterfaceNumber = id;
|
||||
|
||||
/* allocate endpoints */
|
||||
rudolf->in_ep = usb_ep_autoconfig(cdev->gadget, &rudolf_in_fs_desc);
|
||||
if (!rudolf->in_ep) {
|
||||
autoconf_fail:
|
||||
ERROR(cdev, "%s: can't autoconfigure on %s\n",
|
||||
f->name, cdev->gadget->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
rudolf->in_ep->driver_data = cdev; /* claim */
|
||||
|
||||
rudolf->out_ep = usb_ep_autoconfig(cdev->gadget, &rudolf_out_fs_desc);
|
||||
if (!rudolf->out_ep)
|
||||
goto autoconf_fail;
|
||||
rudolf->out_ep->driver_data = cdev; /* claim */
|
||||
|
||||
|
||||
/* support high speed hardware */
|
||||
if (gadget_is_dualspeed(c->cdev->gadget)) {
|
||||
|
||||
rudolf_in_hs_desc.bEndpointAddress =
|
||||
rudolf_in_fs_desc.bEndpointAddress;
|
||||
rudolf_out_hs_desc.bEndpointAddress =
|
||||
rudolf_out_fs_desc.bEndpointAddress;
|
||||
f->hs_descriptors = hs_rudolf_descs;
|
||||
f->descriptors = fs_rudolf_descs;
|
||||
}
|
||||
|
||||
DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
|
||||
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
|
||||
f->name, rudolf->in_ep->name, rudolf->out_ep->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
f_rudolf_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||
{
|
||||
kfree(func_to_rudolf(f));
|
||||
}
|
||||
|
||||
static void usb_req_arm(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (UsbSpeed.Speed == FULL_SPEED)
|
||||
{
|
||||
req->length = 64;
|
||||
req->actual = 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
req->length = 1024;
|
||||
req->actual = 1024;
|
||||
}
|
||||
|
||||
status = usb_ep_queue(ep, req, GFP_ATOMIC);
|
||||
if (status) {
|
||||
usb_ep_set_halt(ep);
|
||||
/* FIXME recover later ... somehow */
|
||||
}
|
||||
}
|
||||
|
||||
static int read_data_from_host(struct usb_request *req)
|
||||
{
|
||||
unsigned i;
|
||||
u8 *buf = req->buf;
|
||||
|
||||
int from_host_length = 0; // NO ACCESS LOCKS YET
|
||||
|
||||
// test for actual length > 0
|
||||
|
||||
for (i = 0; i < req->actual; i++, buf++)
|
||||
{
|
||||
|
||||
usb_char_buffer_out[i] = *buf;
|
||||
from_host_length++;
|
||||
}
|
||||
|
||||
return (from_host_length);
|
||||
}
|
||||
|
||||
static void write_data_to_the_host(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
unsigned i;
|
||||
u8 *buf = req->buf;
|
||||
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("WR to HOST req->length = %d\r\n", req->length);
|
||||
#endif
|
||||
|
||||
#undef DEBUG
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("USB = %d, %d\r\n", usb_char_buffer_in[2], usb_char_buffer_in[3]);
|
||||
#endif
|
||||
#undef DEBUG
|
||||
|
||||
for (i = 0; i < req->length; i++)
|
||||
*buf++ = usb_char_buffer_in[i];
|
||||
usb_char_in_length = 0; // Reset and ready
|
||||
}
|
||||
|
||||
static void rudolf_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
struct f_rudolf *rudolf = ep->driver_data;
|
||||
int status = req->status;
|
||||
|
||||
|
||||
switch ( status ) {
|
||||
|
||||
case 0: /* normal completion? */
|
||||
if (ep == rudolf->out_ep) // An OUT completion?
|
||||
{
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("Rudolf_complete OUT\n");
|
||||
#endif
|
||||
|
||||
usb_char_out_length = read_data_from_host(req);
|
||||
usb_req_arm(ep, req);
|
||||
}
|
||||
else // We have an INPUT request complete
|
||||
{
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("Rudolf_complete IN\n");
|
||||
#endif
|
||||
|
||||
switch(input_state) // State of Brick data x-fer
|
||||
{
|
||||
case USB_DATA_READY: //should be BUSY or PENDING....
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("IN_IN_IN - READY ?????\n");
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
case USB_DATA_PENDING: //
|
||||
// #define DEBUG
|
||||
#ifdef DEBUG
|
||||
printk("IN_IN_IN - PENDING settes to BUSY\n");
|
||||
#endif
|
||||
|
||||
input_state = USB_DATA_BUSY;
|
||||
write_data_to_the_host(ep, req);
|
||||
usb_req_arm(ep, req); // new request
|
||||
break;
|
||||
|
||||
case USB_DATA_BUSY: //
|
||||
#ifdef DEBUG
|
||||
printk("IN_IN_IN - BUSY settes to READY\n");
|
||||
#endif
|
||||
#undef DEBUG
|
||||
input_state = USB_DATA_READY;
|
||||
// and relax
|
||||
break;
|
||||
|
||||
case USB_DATA_IDLE: // too lazy
|
||||
#ifdef DEBUG
|
||||
printk("IN_IN_IN - IDLE\n");
|
||||
#endif
|
||||
//#undef DEBUG
|
||||
|
||||
break;
|
||||
|
||||
default: break; // hmmm.
|
||||
}
|
||||
// Reset the buffer size - Ready again
|
||||
usb_char_in_length = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
/* this endpoint is normally active while we're configured */
|
||||
|
||||
case -ESHUTDOWN: /* disconnect from host */
|
||||
// REMOVED 26102012 (*pUsbSpeed).Speed = FULL_SPEED;
|
||||
case -ECONNABORTED: /* hardware forced ep reset */
|
||||
case -ECONNRESET: /* request dequeued */
|
||||
//case -ESHUTDOWN: /* disconnect from host */
|
||||
if (ep == rudolf->out_ep)
|
||||
read_data_from_host(req);
|
||||
free_ep_req(ep, req);
|
||||
return;
|
||||
|
||||
case -EOVERFLOW: /* buffer overrun on read means that
|
||||
we didn't provide a big enough
|
||||
buffer.
|
||||
*/
|
||||
default:
|
||||
//#if 1
|
||||
// DBG(cdev, "%s complete --> %d, %d/%d\n", ep->name,
|
||||
// status, req->actual, req->length);
|
||||
//#endif
|
||||
case -EREMOTEIO: /* short read */
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int rudolf_start_ep(struct f_rudolf *rudolf, bool is_in)
|
||||
{
|
||||
struct usb_ep *ep;
|
||||
struct usb_request *req;
|
||||
int status;
|
||||
|
||||
ep = is_in ? rudolf->in_ep : rudolf->out_ep;
|
||||
req = alloc_ep_req(ep);
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
|
||||
req->complete = rudolf_complete;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("UsbSpeed.Speed = %d\n\r", UsbSpeed.Speed);
|
||||
#endif
|
||||
|
||||
if (UsbSpeed.Speed == FULL_SPEED)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printk("rudolf_start_ep FULL\n\r");
|
||||
#endif
|
||||
|
||||
(*pUsbSpeed).Speed = FULL_SPEED;
|
||||
req->length = 64; // Full speed max buffer size
|
||||
req->actual = 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printk("rudolf_start_ep HIGH\n\r");
|
||||
#endif
|
||||
|
||||
(*pUsbSpeed).Speed = HIGH_SPEED;
|
||||
req->length = 1024; // High speed max buffer size
|
||||
req->actual = 1024;
|
||||
}
|
||||
|
||||
if (is_in)
|
||||
{
|
||||
save_in_ep = ep;
|
||||
save_in_req = req;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk("req->length = %d ***** Rudolf_Start_Ep_in\n\r", req->length);
|
||||
#endif
|
||||
|
||||
// reinit_write_data(ep, req);
|
||||
input_state = USB_DATA_BUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printk("***** Rudolf_Start_Ep_out\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
status = usb_ep_queue(ep, req, GFP_ATOMIC);
|
||||
|
||||
if (status) {
|
||||
struct usb_composite_dev *cdev;
|
||||
|
||||
cdev = rudolf->function.config->cdev;
|
||||
ERROR(cdev, "start %s %s --> %d\n",
|
||||
is_in ? "IN" : "OUT",
|
||||
ep->name, status);
|
||||
|
||||
free_ep_req(ep, req);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void disable_rudolf(struct f_rudolf *rudolf)
|
||||
{
|
||||
struct usb_composite_dev *cdev;
|
||||
|
||||
cdev = rudolf->function.config->cdev;
|
||||
disable_endpoints(cdev, rudolf->in_ep, rudolf->out_ep);
|
||||
VDBG(cdev, "%s disabled\n", rudolf->function.name);
|
||||
}
|
||||
|
||||
static int
|
||||
enable_rudolf(struct usb_composite_dev *cdev, struct f_rudolf *rudolf)
|
||||
{
|
||||
int result = 0;
|
||||
const struct usb_endpoint_descriptor *ep_in, *ep_out;
|
||||
struct usb_ep *ep;
|
||||
|
||||
ep_in = ep_choose(cdev->gadget, &rudolf_in_hs_desc, &rudolf_in_fs_desc);
|
||||
|
||||
ep_out = ep_choose(cdev->gadget, &rudolf_out_hs_desc, &rudolf_out_fs_desc);
|
||||
|
||||
ep = rudolf->in_ep;
|
||||
|
||||
result = usb_ep_enable(ep, ep_in);
|
||||
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
ep->driver_data = rudolf;
|
||||
|
||||
result = rudolf_start_ep(rudolf, true);
|
||||
|
||||
if (result < 0) {
|
||||
fail:
|
||||
ep = rudolf->in_ep;
|
||||
usb_ep_disable(ep);
|
||||
ep->driver_data = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* one endpoint reads (sinks) anything OUT (from the host) */
|
||||
ep = rudolf->out_ep;
|
||||
result = usb_ep_enable(ep, ep_out);
|
||||
|
||||
if (result < 0)
|
||||
goto fail;
|
||||
|
||||
ep->driver_data = rudolf;
|
||||
|
||||
result = rudolf_start_ep(rudolf, false);
|
||||
|
||||
if (result < 0) {
|
||||
usb_ep_disable(ep);
|
||||
ep->driver_data = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
DBG(cdev, "%s enabled\n", rudolf->function.name);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int f_rudolf_set_alt(struct usb_function *f,
|
||||
unsigned intf, unsigned alt)
|
||||
{
|
||||
struct f_rudolf *rudolf = func_to_rudolf(f);
|
||||
struct usb_composite_dev *cdev = f->config->cdev;
|
||||
|
||||
/* we know alt is zero */
|
||||
if (rudolf->in_ep->driver_data)
|
||||
disable_rudolf(rudolf);
|
||||
|
||||
return enable_rudolf(cdev, rudolf);
|
||||
}
|
||||
|
||||
static void f_rudolf_disable(struct usb_function *f)
|
||||
{
|
||||
struct f_rudolf *rudolf = func_to_rudolf(f);
|
||||
|
||||
disable_rudolf(rudolf);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int rudolf_bind_config(struct usb_configuration *c)
|
||||
{
|
||||
struct f_rudolf *rudolf;
|
||||
int status;
|
||||
|
||||
rudolf = kzalloc(sizeof *rudolf, GFP_KERNEL);
|
||||
if (!rudolf)
|
||||
return -ENOMEM;
|
||||
|
||||
rudolf->function.name = "rudolf xfer";
|
||||
rudolf->function.descriptors = hs_rudolf_descs;
|
||||
rudolf->function.bind = f_rudolf_bind;
|
||||
rudolf->function.unbind = f_rudolf_unbind;
|
||||
rudolf->function.set_alt = f_rudolf_set_alt;
|
||||
rudolf->function.disable = f_rudolf_disable;
|
||||
|
||||
status = usb_add_function(c, &rudolf->function);
|
||||
if (status)
|
||||
kfree(rudolf);
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifndef PCASM
|
||||
static int rudolf_setup(struct usb_configuration *c,
|
||||
const struct usb_ctrlrequest *ctrl)
|
||||
{
|
||||
struct usb_request *req = c->cdev->req;
|
||||
int value = -EOPNOTSUPP;
|
||||
u16 w_index = le16_to_cpu(ctrl->wIndex);
|
||||
u16 w_value = le16_to_cpu(ctrl->wValue);
|
||||
u16 w_length = le16_to_cpu(ctrl->wLength);
|
||||
u16 length = 0;
|
||||
|
||||
/* composite driver infrastructure handles everything except
|
||||
* the two control test requests.
|
||||
*/
|
||||
|
||||
switch (ctrl->bRequest) {
|
||||
|
||||
/*
|
||||
* These are the same vendor-specific requests supported by
|
||||
* Intel's USB 2.0 compliance test devices. We exceed that
|
||||
* device spec by allowing multiple-packet requests.
|
||||
*
|
||||
* NOTE: the Control-OUT data stays in req->buf ... better
|
||||
* would be copying it into a scratch buffer, so that other
|
||||
* requests may safely intervene.
|
||||
*/
|
||||
|
||||
case 0x5b: /* control WRITE test -- fill the buffer */
|
||||
if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR))
|
||||
goto unknown;
|
||||
if (w_value || w_index)
|
||||
break;
|
||||
/* just read that many bytes into the buffer */
|
||||
if (w_length > req->length)
|
||||
break;
|
||||
value = w_length;
|
||||
break;
|
||||
case 0x5c: /* control READ test -- return the buffer */
|
||||
if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR))
|
||||
goto unknown;
|
||||
if (w_value || w_index)
|
||||
break;
|
||||
/* expect those bytes are still in the buffer; send back */
|
||||
if (w_length > req->length)
|
||||
break;
|
||||
value = w_length;
|
||||
break;
|
||||
|
||||
default:
|
||||
unknown:
|
||||
VDBG(c->cdev,
|
||||
"unknown control req%02x.%02x v%04x i%04x l%d\n",
|
||||
ctrl->bRequestType, ctrl->bRequest,
|
||||
w_value, w_index, w_length);
|
||||
}
|
||||
|
||||
//HER SKAL HID DESC SENDES!!!
|
||||
switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
|
||||
|
||||
|
||||
case ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8
|
||||
| USB_REQ_GET_DESCRIPTOR):
|
||||
switch (w_value >> 8) {
|
||||
case HID_DT_REPORT:
|
||||
//VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: REPORT\n");
|
||||
length = w_length;
|
||||
length = min_t(unsigned short, length,
|
||||
sizeof hs_hid_report_descriptor);
|
||||
memcpy(req->buf, hs_hid_report_descriptor, length);
|
||||
value = length;
|
||||
goto respond;
|
||||
break;
|
||||
|
||||
default:
|
||||
//VDBG(cdev, "Unknown decriptor request 0x%x\n",
|
||||
// value >> 8);
|
||||
goto stall;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//VDBG(cdev, "Unknown request 0x%x\n",
|
||||
// ctrl->bRequest);
|
||||
goto stall;
|
||||
break;
|
||||
}
|
||||
|
||||
//HERTIL
|
||||
/* respond with data transfer or status phase? */
|
||||
stall:
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
respond:
|
||||
if (value >= 0) {
|
||||
VDBG(c->cdev, "source/sink req%02x.%02x v%04x i%04x l%d\n",
|
||||
ctrl->bRequestType, ctrl->bRequest,
|
||||
w_value, w_index, w_length);
|
||||
req->zero = 0;
|
||||
req->length = value;
|
||||
value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC);
|
||||
if (value < 0)
|
||||
ERROR(c->cdev, "source/sinkc response, err %d\n",
|
||||
value);
|
||||
}
|
||||
|
||||
/* device either stalls (value < 0) or reports success */
|
||||
return value;
|
||||
}
|
||||
#else
|
||||
// Keep Eclipse happy
|
||||
#endif
|
||||
|
||||
static struct usb_configuration rudolf_driver = {
|
||||
.label = "rudolf driver",
|
||||
.strings = rudolf_strings,
|
||||
.bind = rudolf_bind_config,
|
||||
.setup = rudolf_setup,
|
||||
.bConfigurationValue = 1,
|
||||
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
|
||||
/* .iConfiguration = DYNAMIC */
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
int rudolf_add(struct usb_composite_dev *cdev, bool autoresume)
|
||||
{
|
||||
int id;
|
||||
|
||||
/* allocate string ID(s) */
|
||||
id = usb_string_id(cdev);
|
||||
if (id < 0)
|
||||
return id;
|
||||
strings_rudolf[0].id = id;
|
||||
|
||||
rudolf_intf.iInterface = id;
|
||||
rudolf_driver.iConfiguration = 1; // id;
|
||||
|
||||
/* support autoresume for remote wakeup testing */
|
||||
if (autoresume)
|
||||
rudolf_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
|
||||
|
||||
/* support OTG systems */
|
||||
if (gadget_is_otg(cdev->gadget)) {
|
||||
rudolf_driver.descriptors = otg_desc;
|
||||
rudolf_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
|
||||
}
|
||||
|
||||
return usb_add_config(cdev, &rudolf_driver);
|
||||
}
|
7
brick/mk
Executable file
7
brick/mk
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -xe
|
||||
scp -qr kernel uf2daemon Makefile vm:linux/pxt/
|
||||
ssh vm "cd linux/pxt; make $1"
|
||||
mkdir -p bin
|
||||
scp vm:linux/pxt/bin/* bin/
|
||||
|
34
brick/scripts/dump.js
Normal file
34
brick/scripts/dump.js
Normal file
@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
|
||||
let fs = require("fs")
|
||||
|
||||
let styles = {
|
||||
"0": "rxtx",
|
||||
"1": " tx",
|
||||
"2": "rx ",
|
||||
}
|
||||
|
||||
function build() {
|
||||
let kern = fs.readFileSync( "foo")
|
||||
let off = 0x0001df30
|
||||
|
||||
kern = kern.slice(off + 6 * 5, off + 6 * (5 + 6))
|
||||
console.log(kern.toString("hex"))
|
||||
off = 0
|
||||
|
||||
for (let i = 0; i < 30; ++i) {
|
||||
if (kern[off+4] == 64) {
|
||||
kern[off+4] = 0
|
||||
kern[off+5] = 2
|
||||
}
|
||||
if(kern[off] == 3 || kern[off] == 4) {
|
||||
kern[off+4] = 0
|
||||
kern[off+5] = 1
|
||||
}
|
||||
console.log(`ep=${kern[off]} style=${styles[kern[off+1]]} buf=${kern[off+2] == 0 ? "sin" : kern[off+2] == 1 ? "dbl" : "XXX"} pad=${kern[off+3]} sz=${kern[off+4]+(kern[off+5]<<8)}`)
|
||||
off += 6
|
||||
}
|
||||
console.log(kern.toString("hex"))
|
||||
}
|
||||
|
||||
build()
|
33
brick/scripts/img.js
Normal file
33
brick/scripts/img.js
Normal file
@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
|
||||
let fs = require("fs")
|
||||
|
||||
function build() {
|
||||
let cr = fs.readFileSync("cram.bin")
|
||||
if (cr.length > 10878976) {
|
||||
console.log("too big")
|
||||
return
|
||||
}
|
||||
let img = fs.readFileSync("boot.bin")
|
||||
let off = 0x250000
|
||||
if (img[off] != 0x45 || img[off + 1] != 0x3d) {
|
||||
console.log("bad magic: " + img[off] + " / " + img[off+1])
|
||||
return
|
||||
}
|
||||
|
||||
cr.copy(img, off)
|
||||
|
||||
let kern = fs.readFileSync("piggy-patched.gzip")
|
||||
off = 0x0005540f
|
||||
|
||||
if (img[off] != kern[0] || img[off+1] != kern[1]) {
|
||||
console.log("bad kernel magic: " + img[off] + " / " + img[off+1])
|
||||
return
|
||||
}
|
||||
|
||||
kern.copy(img, off)
|
||||
|
||||
fs.writeFileSync("firmware.bin", img)
|
||||
}
|
||||
|
||||
build()
|
4
brick/scripts/mkimg
Executable file
4
brick/scripts/mkimg
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
sudo mkfs.cramfs dev-ev3 cram.bin
|
||||
node img
|
||||
ls -l firmware.bin
|
8
brick/scripts/patchkern.js
Normal file
8
brick/scripts/patchkern.js
Normal file
@ -0,0 +1,8 @@
|
||||
let small = "010100000004010200000004020100004000020200004000030100000004040000008000"
|
||||
let big = "010100000004010200000004020100000002020200000002030100000001040000000001"
|
||||
|
||||
let fs = require("fs")
|
||||
|
||||
let kern = fs.readFileSync( "foo")
|
||||
let kern2 = new Buffer(kern.toString("hex").replace(small, big), "hex")
|
||||
fs.writeFileSync("foo2", kern2)
|
9
brick/send
Executable file
9
brick/send
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
./mk
|
||||
ev3duder up bin/d_usbdev.ko ../prjs/ko/d_usbdev.ko
|
||||
ev3duder up bin/nbd.ko ../prjs/ko/nbd.ko
|
||||
ev3duder up ins ../prjs/ko/ins
|
||||
ev3duder exec 'rm ../prjs/ko/uf2d'
|
||||
ev3duder up bin/uf2d ../prjs/ko/uf2d
|
||||
|
6
brick/uf2daemon/Makefile
Normal file
6
brick/uf2daemon/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
CFLAGS = -std=c99 -W -Wall
|
||||
SRC = main.c fat.c
|
||||
|
||||
all:
|
||||
gcc -DX86=1 -g $(CFLAGS) $(SRC) -o server86
|
||||
arm-none-linux-gnueabi-gcc -Os -s $(CFLAGS) $(SRC) -o server
|
784
brick/uf2daemon/fat.c
Normal file
784
brick/uf2daemon/fat.c
Normal file
@ -0,0 +1,784 @@
|
||||
|
||||
#define VENDOR_NAME "The LEGO Group"
|
||||
#define PRODUCT_NAME "Mindstorms EV3"
|
||||
#define VOLUME_LABEL "EV3"
|
||||
#define INDEX_URL "https://makecode.com/lego"
|
||||
|
||||
#define BOARD_ID "LEGO-EV3-v0"
|
||||
|
||||
#define _XOPEN_SOURCE 500
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#define max(a, b) \
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a > _b ? _a : _b; \
|
||||
})
|
||||
|
||||
#define min(a, b) \
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a < _b ? _a : _b; \
|
||||
})
|
||||
|
||||
#include "uf2.h"
|
||||
|
||||
#define DBG printf
|
||||
|
||||
typedef struct {
|
||||
uint8_t JumpInstruction[3];
|
||||
uint8_t OEMInfo[8];
|
||||
uint16_t SectorSize;
|
||||
uint8_t SectorsPerCluster;
|
||||
uint16_t ReservedSectors;
|
||||
uint8_t FATCopies;
|
||||
uint16_t RootDirectoryEntries;
|
||||
uint16_t TotalSectors16;
|
||||
uint8_t MediaDescriptor;
|
||||
uint16_t SectorsPerFAT;
|
||||
uint16_t SectorsPerTrack;
|
||||
uint16_t Heads;
|
||||
uint32_t HiddenSectors;
|
||||
uint32_t TotalSectors32;
|
||||
uint8_t PhysicalDriveNum;
|
||||
uint8_t Reserved;
|
||||
uint8_t ExtendedBootSig;
|
||||
uint32_t VolumeSerialNumber;
|
||||
char VolumeLabel[11];
|
||||
uint8_t FilesystemIdentifier[8];
|
||||
} __attribute__((packed)) FAT_BootBlock;
|
||||
|
||||
typedef struct {
|
||||
char name[8];
|
||||
char ext[3];
|
||||
uint8_t attrs;
|
||||
uint8_t reserved;
|
||||
uint8_t createTimeFine;
|
||||
uint16_t createTime;
|
||||
uint16_t createDate;
|
||||
uint16_t lastAccessDate;
|
||||
uint16_t highStartCluster;
|
||||
uint16_t updateTime;
|
||||
uint16_t updateDate;
|
||||
uint16_t startCluster;
|
||||
uint32_t size;
|
||||
} __attribute__((packed)) DirEntry;
|
||||
|
||||
typedef struct {
|
||||
uint8_t seqno;
|
||||
uint16_t name0[5];
|
||||
uint8_t attrs;
|
||||
uint8_t type;
|
||||
uint8_t checksum;
|
||||
uint16_t name1[6];
|
||||
uint16_t startCluster;
|
||||
uint16_t name2[2];
|
||||
} __attribute__((packed)) VFatEntry;
|
||||
|
||||
STATIC_ASSERT(sizeof(DirEntry) == 32);
|
||||
|
||||
#define STR0(x) #x
|
||||
#define STR(x) STR0(x)
|
||||
const char infoUf2File[] = //
|
||||
"UF2 Bootloader " UF2_VERSION "\r\n"
|
||||
"Model: " PRODUCT_NAME "\r\n"
|
||||
"Board-ID: " BOARD_ID "\r\n";
|
||||
|
||||
const char indexFile[] = //
|
||||
"<!doctype html>\n"
|
||||
"<html>"
|
||||
"<body>"
|
||||
"<script>\n"
|
||||
"location.replace(\"" INDEX_URL "\");\n"
|
||||
"</script>"
|
||||
"</body>"
|
||||
"</html>\n";
|
||||
|
||||
#define RESERVED_SECTORS 1
|
||||
#define ROOT_DIR_SECTORS 4
|
||||
#define SECTORS_PER_FAT ((NUM_FAT_BLOCKS * 2 + 511) / 512)
|
||||
|
||||
#define START_FAT0 RESERVED_SECTORS
|
||||
#define START_FAT1 (START_FAT0 + SECTORS_PER_FAT)
|
||||
#define START_ROOTDIR (START_FAT1 + SECTORS_PER_FAT)
|
||||
#define START_CLUSTERS (START_ROOTDIR + ROOT_DIR_SECTORS)
|
||||
#define ROOT_DIR_ENTRIES (ROOT_DIR_SECTORS * 512 / 32)
|
||||
|
||||
#define F_TEXT 1
|
||||
#define F_UF2 2
|
||||
#define F_DIR 4
|
||||
#define F_CONT 8
|
||||
|
||||
static const FAT_BootBlock BootBlock = {
|
||||
.JumpInstruction = {0xeb, 0x3c, 0x90},
|
||||
.OEMInfo = "UF2 UF2 ",
|
||||
.SectorSize = 512,
|
||||
.SectorsPerCluster = 1,
|
||||
.ReservedSectors = RESERVED_SECTORS,
|
||||
.FATCopies = 2,
|
||||
.RootDirectoryEntries = ROOT_DIR_ENTRIES,
|
||||
.TotalSectors16 = NUM_FAT_BLOCKS - 2,
|
||||
.MediaDescriptor = 0xF8,
|
||||
.SectorsPerFAT = SECTORS_PER_FAT,
|
||||
.SectorsPerTrack = 1,
|
||||
.Heads = 1,
|
||||
.ExtendedBootSig = 0x29,
|
||||
.VolumeSerialNumber = 0x00420042,
|
||||
.VolumeLabel = VOLUME_LABEL,
|
||||
.FilesystemIdentifier = "FAT16 ",
|
||||
};
|
||||
|
||||
int currCluster = 2;
|
||||
struct FsEntry *rootDir;
|
||||
struct ClusterData *firstCluster, *lastCluster;
|
||||
|
||||
typedef struct ClusterData {
|
||||
int flags;
|
||||
int numclusters;
|
||||
struct stat st;
|
||||
struct ClusterData *dnext;
|
||||
struct ClusterData *cnext;
|
||||
struct FsEntry *dirdata;
|
||||
struct FsEntry *myfile;
|
||||
char name[0];
|
||||
} ClusterData;
|
||||
|
||||
typedef struct FsEntry {
|
||||
int startCluster;
|
||||
uint8_t attrs;
|
||||
int size;
|
||||
int numdirentries;
|
||||
time_t ctime, mtime;
|
||||
struct FsEntry *next;
|
||||
struct ClusterData *data;
|
||||
char fatname[12];
|
||||
char vfatname[0];
|
||||
} FsEntry;
|
||||
|
||||
struct DirMap {
|
||||
const char *mapName;
|
||||
const char *fsName;
|
||||
};
|
||||
|
||||
struct DirMap dirMaps[] = { //
|
||||
#ifdef X86
|
||||
{"foo qux baz", "dirs/bar"}, //
|
||||
{"foo", "dirs/foo"}, //
|
||||
{"xyz", "dirs/bar2"}, //
|
||||
#else
|
||||
{"Projects", "/mnt/ramdisk/prjs/BrkProg_SAVE"},
|
||||
{"SD Card", "/media/card/myapps"},
|
||||
{"USB Stick", "/media/usb/myapps"},
|
||||
#endif
|
||||
{NULL, NULL}};
|
||||
|
||||
void timeToFat(time_t t, uint16_t *dateP, uint16_t *timeP) {
|
||||
struct tm tm;
|
||||
|
||||
localtime_r(&t, &tm);
|
||||
|
||||
if (timeP)
|
||||
*timeP = (tm.tm_hour << 11) | (tm.tm_min << 5) | (tm.tm_sec / 2);
|
||||
|
||||
if (dateP)
|
||||
*dateP = (max(0, tm.tm_year - 80) << 9) | ((tm.tm_mon + 1) << 5) | tm.tm_mday;
|
||||
}
|
||||
|
||||
void padded_memcpy(char *dst, const char *src, int len) {
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (*src)
|
||||
*dst = *src++;
|
||||
else
|
||||
*dst = ' ';
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
char *expandMap(const char *mapName) {
|
||||
static char mapbuf[300];
|
||||
|
||||
const char *rest = "";
|
||||
for (int i = 0; i < (int)sizeof(mapbuf); ++i) {
|
||||
char c = mapName[i];
|
||||
if (c == '/' || c == 0) {
|
||||
mapbuf[i] = 0;
|
||||
rest = mapName + i;
|
||||
break;
|
||||
}
|
||||
mapbuf[i] = c;
|
||||
}
|
||||
for (int i = 0; dirMaps[i].mapName; ++i) {
|
||||
if (strcmp(dirMaps[i].mapName, mapbuf) == 0) {
|
||||
strcpy(mapbuf, dirMaps[i].fsName);
|
||||
strcat(mapbuf, rest);
|
||||
return mapbuf;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ClusterData *mkClusterData(int namelen) {
|
||||
ClusterData *c = malloc(sizeof(*c) + namelen + 1);
|
||||
memset(c, 0, sizeof(*c) + namelen + 1);
|
||||
return c;
|
||||
}
|
||||
|
||||
ClusterData *readDir(const char *mapName) {
|
||||
DIR *d = opendir(expandMap(mapName));
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
ClusterData *res = NULL;
|
||||
for (;;) {
|
||||
struct dirent *ent = readdir(d);
|
||||
if (!ent)
|
||||
break;
|
||||
|
||||
ClusterData *c = mkClusterData(strlen(mapName) + 1 + strlen(ent->d_name));
|
||||
|
||||
c->flags = F_UF2;
|
||||
c->dnext = res;
|
||||
sprintf(c->name, "%s/%s", mapName, ent->d_name);
|
||||
|
||||
int err = stat(expandMap(c->name), &c->st);
|
||||
assert(err >= 0);
|
||||
|
||||
if (S_ISREG(c->st.st_mode) && strlen(c->name) < UF2_FILENAME_MAX) {
|
||||
c->numclusters = (c->st.st_size + 255) / 256;
|
||||
} else {
|
||||
free(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
res = c;
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
return res;
|
||||
}
|
||||
|
||||
int filechar(int c) {
|
||||
if (!c)
|
||||
return 0;
|
||||
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') ||
|
||||
strchr("_-", c);
|
||||
}
|
||||
|
||||
void copyFsChars(char *dst, const char *src, int len) {
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (filechar(*src))
|
||||
dst[i] = toupper(*src++);
|
||||
else {
|
||||
if (*src == '.')
|
||||
src = "";
|
||||
if (*src == 0)
|
||||
dst[i] = ' ';
|
||||
else
|
||||
dst[i] = '_';
|
||||
while (*src && !filechar(*src))
|
||||
src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FsEntry *mkFsEntry(const char *name) {
|
||||
int sz = sizeof(FsEntry) + strlen(name) + 1;
|
||||
FsEntry *e = malloc(sz);
|
||||
memset(e, 0, sz);
|
||||
e->startCluster = currCluster;
|
||||
e->next = NULL;
|
||||
// +1 for final 0x0000, and +12 for alignment
|
||||
e->numdirentries = 1 + (strlen(name) + 1 + 12) / 13;
|
||||
strcpy(e->vfatname, name);
|
||||
|
||||
const char *src = name;
|
||||
copyFsChars(e->fatname, src, 8);
|
||||
while (*src && *src != '.')
|
||||
src++;
|
||||
if (*src == '.')
|
||||
src++;
|
||||
else
|
||||
src = "";
|
||||
copyFsChars(e->fatname + 8, src, 3);
|
||||
return e;
|
||||
}
|
||||
|
||||
void addClusterData(ClusterData *c, FsEntry *e) {
|
||||
currCluster += c->numclusters;
|
||||
|
||||
if (firstCluster == NULL) {
|
||||
firstCluster = c;
|
||||
} else {
|
||||
lastCluster->cnext = c;
|
||||
}
|
||||
lastCluster = c;
|
||||
|
||||
if (c->st.st_ctime)
|
||||
e->ctime = min(e->ctime, c->st.st_ctime);
|
||||
e->mtime = max(e->mtime, c->st.st_mtime);
|
||||
|
||||
c->myfile = e;
|
||||
|
||||
DBG("add cluster: flags=%d size=%d numcl=%d name=%s\n", c->flags, (int)c->st.st_size,
|
||||
c->numclusters, c->name);
|
||||
}
|
||||
|
||||
FsEntry *addRootText(const char *filename, const char *contents) {
|
||||
FsEntry *e = mkFsEntry(filename);
|
||||
e->next = rootDir;
|
||||
rootDir = e;
|
||||
|
||||
int sz = strlen(contents);
|
||||
e->size = sz;
|
||||
if (sz > 0) {
|
||||
assert(sz <= 512);
|
||||
ClusterData *c = mkClusterData(sz);
|
||||
c->st.st_mtime = c->st.st_ctime = time(NULL);
|
||||
|
||||
c->flags = F_TEXT;
|
||||
strcpy(c->name, contents);
|
||||
c->st.st_size = sz;
|
||||
c->numclusters = 1;
|
||||
addClusterData(c, e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
int baseLen(const char *a) {
|
||||
int len = 0;
|
||||
while (*a && *a != '.') {
|
||||
a++;
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int nameMatches(const char *a, const char *b) {
|
||||
for (;;) {
|
||||
if ((*a == 0 || *a == '.') && (*b == 0 || *b == '.'))
|
||||
return 1;
|
||||
|
||||
if (*a != *b)
|
||||
return 0;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
|
||||
void setFatNames(FsEntry *dirent) {
|
||||
for (FsEntry *p = dirent; p; p = p->next) {
|
||||
// check for collisions
|
||||
int k = 1;
|
||||
retry:
|
||||
for (FsEntry *o = dirent; o && o != p; o = o->next) {
|
||||
if (strcmp(o->fatname, p->fatname) == 0) {
|
||||
char buf[20];
|
||||
sprintf(buf, "~%d", k++);
|
||||
int len = strlen(buf);
|
||||
memcpy(p->fatname + 8 - len, buf, len);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
DBG("setname: %s [%s] cl=%s @ %d sz=%d dents=%d\n", p->vfatname, p->fatname,
|
||||
p->data ? p->data->name : "(no data)", p->startCluster, p->size, p->numdirentries);
|
||||
}
|
||||
}
|
||||
|
||||
void addFullDir(const char *mapName) {
|
||||
int numEntries = 0;
|
||||
FsEntry *dirents = NULL;
|
||||
|
||||
time_t mtime = 0, ctime = 0;
|
||||
|
||||
for (ClusterData *cl = readDir(mapName); cl; cl = cl->dnext) {
|
||||
if (cl->cnext || cl == lastCluster)
|
||||
continue; // already done
|
||||
|
||||
// vfat entries
|
||||
const char *filename = strchr(cl->name, '/') + 1;
|
||||
int len = baseLen(filename) + 4;
|
||||
char namebuf[len];
|
||||
memcpy(namebuf, filename, len - 4);
|
||||
strcpy(namebuf + len - 4, ".uf2");
|
||||
|
||||
assert(cl->flags & F_UF2);
|
||||
|
||||
FsEntry *fent = mkFsEntry(namebuf);
|
||||
numEntries += fent->numdirentries;
|
||||
fent->next = dirents;
|
||||
fent->data = cl;
|
||||
fent->size = cl->numclusters * 512;
|
||||
dirents = fent;
|
||||
addClusterData(cl, fent);
|
||||
for (ClusterData *other = cl->dnext; other; other = other->dnext) {
|
||||
if (nameMatches(cl->name, other->name)) {
|
||||
other->flags |= F_CONT;
|
||||
fent->size += other->numclusters * 512;
|
||||
addClusterData(other, fent);
|
||||
}
|
||||
}
|
||||
if (mtime == 0) {
|
||||
mtime = fent->mtime;
|
||||
ctime = fent->ctime;
|
||||
} else {
|
||||
mtime = max(mtime, fent->mtime);
|
||||
ctime = min(ctime, fent->ctime);
|
||||
}
|
||||
}
|
||||
|
||||
setFatNames(dirents);
|
||||
|
||||
FsEntry *dent = mkFsEntry(mapName);
|
||||
dent->data = mkClusterData(0);
|
||||
dent->data->dirdata = dirents;
|
||||
dent->data->numclusters = (numEntries + 16) / 16; // at least 1
|
||||
addClusterData(dent->data, dent);
|
||||
dent->mtime = mtime;
|
||||
dent->ctime = ctime;
|
||||
dent->next = rootDir;
|
||||
dent->attrs = 0x10;
|
||||
dent->data->flags = F_DIR;
|
||||
rootDir = dent;
|
||||
}
|
||||
|
||||
void setupFs() {
|
||||
addRootText("info_uf2.txt", infoUf2File);
|
||||
addRootText("index.html", indexFile);
|
||||
for (int i = 0; dirMaps[i].mapName; ++i) {
|
||||
addFullDir(dirMaps[i].mapName);
|
||||
}
|
||||
|
||||
setFatNames(rootDir); // make names unique
|
||||
|
||||
FsEntry *e = addRootText(BootBlock.VolumeLabel, "");
|
||||
e->numdirentries = 1;
|
||||
e->attrs = 0x28;
|
||||
}
|
||||
|
||||
#define WRITE_ENT(v) \
|
||||
do { \
|
||||
if (skip++ >= 0) \
|
||||
*dest++ = v; \
|
||||
if (skip >= 256) \
|
||||
return; \
|
||||
cl++; \
|
||||
} while (0)
|
||||
|
||||
void readFat(uint16_t *dest, int skip) {
|
||||
int cl = 0;
|
||||
skip = -skip;
|
||||
WRITE_ENT(0xfff0);
|
||||
WRITE_ENT(0xffff);
|
||||
for (ClusterData *c = firstCluster; c; c = c->cnext) {
|
||||
for (int i = 0; i < c->numclusters - 1; i++)
|
||||
WRITE_ENT(cl + 1);
|
||||
if (c->cnext && c->cnext->flags & F_CONT)
|
||||
WRITE_ENT(cl + 1);
|
||||
else
|
||||
WRITE_ENT(0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
// note that ptr might be unaligned
|
||||
const char *copyVFatName(const char *ptr, void *dest, int len) {
|
||||
uint8_t *dst = dest;
|
||||
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (ptr == NULL) {
|
||||
*dst++ = 0xff;
|
||||
*dst++ = 0xff;
|
||||
} else {
|
||||
*dst++ = *ptr;
|
||||
*dst++ = 0;
|
||||
if (*ptr)
|
||||
ptr++;
|
||||
else
|
||||
ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint8_t fatChecksum(const char *name) {
|
||||
uint8_t sum = 0;
|
||||
for (int i = 0; i < 11; ++i)
|
||||
sum = ((sum & 1) << 7) + (sum >> 1) + *name++;
|
||||
return sum;
|
||||
}
|
||||
|
||||
void readDirData(uint8_t *dest, FsEntry *dirdata, int blkno) {
|
||||
DirEntry *d = (void *)dest;
|
||||
int idx = blkno * -16;
|
||||
for (FsEntry *e = dirdata; e; e = e->next) {
|
||||
if (idx >= 16)
|
||||
break;
|
||||
|
||||
// DBG("dir idx=%d %s\n", idx, e->vfatname);
|
||||
|
||||
for (int i = 0; i < e->numdirentries; ++i, ++idx) {
|
||||
if (0 <= idx && idx < 16) {
|
||||
if (i == e->numdirentries - 1) {
|
||||
memcpy(d->name, e->fatname, 11);
|
||||
d->attrs = e->attrs;
|
||||
d->size = e->size;
|
||||
d->startCluster = e->startCluster;
|
||||
timeToFat(e->mtime, &d->updateDate, &d->updateTime);
|
||||
timeToFat(e->ctime, &d->createDate, &d->createTime);
|
||||
} else {
|
||||
VFatEntry *f = (void *)d;
|
||||
int seq = e->numdirentries - i - 2;
|
||||
f->seqno = seq + 1; // they start at 1
|
||||
if (i == 0)
|
||||
f->seqno |= 0x40;
|
||||
f->attrs = 0x0F;
|
||||
f->type = 0x00;
|
||||
f->checksum = fatChecksum(e->fatname);
|
||||
f->startCluster = 0;
|
||||
|
||||
const char *ptr = e->vfatname + (13 * seq);
|
||||
ptr = copyVFatName(ptr, f->name0, 5);
|
||||
ptr = copyVFatName(ptr, f->name1, 6);
|
||||
ptr = copyVFatName(ptr, f->name2, 2);
|
||||
}
|
||||
d++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void readBlock(uint8_t *dest, int blkno) {
|
||||
// DBG("readbl %d\n", blkno);
|
||||
int blkno0 = blkno;
|
||||
for (ClusterData *c = firstCluster; c; c = c->cnext) {
|
||||
// DBG("off=%d sz=%d\n", blkno, c->numclusters);
|
||||
if (blkno >= c->numclusters) {
|
||||
blkno -= c->numclusters;
|
||||
continue;
|
||||
}
|
||||
// DBG("readbl off=%d %p\n", blkno, c);
|
||||
if (c->dirdata) {
|
||||
readDirData(dest, c->dirdata, blkno);
|
||||
} else if (c->flags & F_TEXT) {
|
||||
strcpy((char *)dest, c->name);
|
||||
} else if (c->flags & F_UF2) {
|
||||
UF2_Block *bl = (void *)dest;
|
||||
|
||||
bl->magicStart0 = UF2_MAGIC_START0;
|
||||
bl->magicStart1 = UF2_MAGIC_START1;
|
||||
bl->magicEnd = UF2_MAGIC_END;
|
||||
bl->flags = UF2_FLAG_FILE;
|
||||
bl->blockNo = blkno0 - (c->myfile->startCluster - 2);
|
||||
bl->numBlocks = c->myfile->size / 512;
|
||||
bl->targetAddr = blkno * 256;
|
||||
bl->payloadSize = 256;
|
||||
bl->fileSize = c->st.st_size;
|
||||
|
||||
int fd = open(expandMap(c->name), O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
lseek(fd, bl->targetAddr, SEEK_SET);
|
||||
bl->payloadSize = read(fd, bl->data, 256);
|
||||
} else {
|
||||
bl->payloadSize = -1;
|
||||
}
|
||||
|
||||
if (bl->payloadSize < 475 - strlen(c->name))
|
||||
strcpy((char *)bl->data + bl->payloadSize, c->name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void read_block(uint32_t block_no, uint8_t *data) {
|
||||
memset(data, 0, 512);
|
||||
uint32_t sectionIdx = block_no;
|
||||
|
||||
if (block_no == 0) {
|
||||
memcpy(data, &BootBlock, sizeof(BootBlock));
|
||||
data[510] = 0x55;
|
||||
data[511] = 0xaa;
|
||||
// logval("data[0]", data[0]);
|
||||
} else if (block_no < START_ROOTDIR) {
|
||||
sectionIdx -= START_FAT0;
|
||||
if (sectionIdx >= SECTORS_PER_FAT) // second copy of fat?
|
||||
sectionIdx -= SECTORS_PER_FAT;
|
||||
|
||||
readFat((void *)data, sectionIdx * 256);
|
||||
} else if (block_no < START_CLUSTERS) {
|
||||
sectionIdx -= START_ROOTDIR;
|
||||
readDirData(data, rootDir, sectionIdx);
|
||||
} else {
|
||||
sectionIdx -= START_CLUSTERS;
|
||||
readBlock(data, sectionIdx);
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_BLOCKS 8000
|
||||
typedef struct {
|
||||
uint32_t numBlocks;
|
||||
uint32_t numWritten;
|
||||
uint8_t writtenMask[MAX_BLOCKS / 8 + 1];
|
||||
} WriteState;
|
||||
|
||||
char elfPath[300];
|
||||
|
||||
int lmsPid;
|
||||
void stopLMS() {
|
||||
struct dirent *ent;
|
||||
DIR *dir;
|
||||
|
||||
dir = opendir("/proc");
|
||||
if (dir == NULL)
|
||||
return;
|
||||
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
int pid = atoi(ent->d_name);
|
||||
if (!pid)
|
||||
continue;
|
||||
char namebuf[100];
|
||||
snprintf(namebuf, 1000, "/proc/%d/cmdline", pid);
|
||||
FILE *f = fopen(namebuf, "r");
|
||||
if (f) {
|
||||
fread(namebuf, 1, 99, f);
|
||||
if (strcmp(namebuf, "./lms2012") == 0) {
|
||||
lmsPid = pid;
|
||||
}
|
||||
fclose(f);
|
||||
if (lmsPid)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
if (lmsPid) {
|
||||
DBG("SIGSTOP to lmsPID=%d\n", lmsPid);
|
||||
kill(lmsPid, SIGSTOP);
|
||||
} else {
|
||||
DBG("LMS not found\n");
|
||||
}
|
||||
}
|
||||
|
||||
void waitAndContinue() {
|
||||
stopLMS();
|
||||
for (int fd = 3; fd < 9999; ++fd)
|
||||
close(fd);
|
||||
pid_t child = fork();
|
||||
if (child == 0) {
|
||||
DBG("start %s\n", elfPath);
|
||||
execl(elfPath, elfPath, "--msd", (char*) NULL);
|
||||
exit(128);
|
||||
}
|
||||
int status;
|
||||
waitpid(child, &status, 0);
|
||||
DBG("re-start LMS\n");
|
||||
if (lmsPid)
|
||||
kill(lmsPid, SIGCONT);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void restartProgram() {
|
||||
if (!elfPath[0])
|
||||
exit(0);
|
||||
|
||||
pid_t child = fork();
|
||||
if (child == 0)
|
||||
waitAndContinue();
|
||||
else
|
||||
exit(0); // causes parent to eject MSD etc
|
||||
}
|
||||
|
||||
static WriteState wrState;
|
||||
void write_block(uint32_t block_no, uint8_t *data) {
|
||||
WriteState *state = &wrState;
|
||||
|
||||
UF2_Block *bl = (void *)data;
|
||||
|
||||
if (!is_uf2_block(bl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void)block_no;
|
||||
|
||||
bl->data[475] = 0; // make sure we have NUL terminator
|
||||
char *fn0 = (char *)bl->data + bl->payloadSize;
|
||||
int namelen = 0;
|
||||
if (bl->payloadSize <= UF2_MAX_PAYLOAD) {
|
||||
namelen = strlen(fn0);
|
||||
}
|
||||
|
||||
if ((bl->flags & UF2_FLAG_FILE) && bl->fileSize <= UF2_MAX_FILESIZE &&
|
||||
bl->targetAddr < bl->fileSize && 1 <= namelen && namelen <= UF2_FILENAME_MAX) {
|
||||
|
||||
char *firstSL = strchr(fn0, '/');
|
||||
char *lastSL = strrchr(fn0, '/');
|
||||
if (!lastSL)
|
||||
lastSL = fn0;
|
||||
else
|
||||
lastSL++;
|
||||
int baseLen = strlen(lastSL);
|
||||
char fallback[strlen(dirMaps[0].fsName) + 1 + baseLen + 1];
|
||||
sprintf(fallback, "%s/%s", dirMaps[0].fsName, lastSL);
|
||||
char *fn = NULL;
|
||||
|
||||
if (firstSL && firstSL + 1 == lastSL)
|
||||
fn = expandMap(fn0);
|
||||
if (!fn)
|
||||
fn = fallback;
|
||||
|
||||
char *p = strrchr(fn, '/');
|
||||
*p = 0;
|
||||
mkdir(fn, 0777);
|
||||
*p = '/';
|
||||
|
||||
int fd = open(fn, O_WRONLY | O_CREAT, 0777);
|
||||
if (fd >= 0) {
|
||||
ftruncate(fd, bl->fileSize);
|
||||
lseek(fd, bl->targetAddr, SEEK_SET);
|
||||
// DBG("write %d bytes at %d to %s\n", bl->payloadSize, bl->targetAddr, fn);
|
||||
write(fd, bl->data, bl->payloadSize);
|
||||
close(fd);
|
||||
|
||||
if (strlen(fn) > 4 && !strcmp(fn + strlen(fn) - 4, ".elf")) {
|
||||
strcpy(elfPath, fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state && bl->numBlocks) {
|
||||
if (state->numBlocks != bl->numBlocks) {
|
||||
if (bl->numBlocks >= MAX_BLOCKS || state->numBlocks)
|
||||
state->numBlocks = 0xffffffff;
|
||||
else
|
||||
state->numBlocks = bl->numBlocks;
|
||||
}
|
||||
if (bl->blockNo < MAX_BLOCKS) {
|
||||
uint8_t mask = 1 << (bl->blockNo % 8);
|
||||
uint32_t pos = bl->blockNo / 8;
|
||||
if (!(state->writtenMask[pos] & mask)) {
|
||||
// logval("incr", state->numWritten);
|
||||
state->writtenMask[pos] |= mask;
|
||||
state->numWritten++;
|
||||
}
|
||||
if (state->numWritten >= state->numBlocks) {
|
||||
restartProgram();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO timeout for restart?
|
||||
}
|
||||
}
|
210
brick/uf2daemon/main.c
Normal file
210
brick/uf2daemon/main.c
Normal file
@ -0,0 +1,210 @@
|
||||
#define _GNU_SOURCE 1
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <linux/nbd.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/fs.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "uf2.h"
|
||||
|
||||
#define NUM_BLOCKS NUM_FAT_BLOCKS
|
||||
|
||||
#define FAIL(args...) \
|
||||
do { \
|
||||
fprintf(stderr, args); \
|
||||
fprintf(stderr, "\n"); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
#define LOG(args...) \
|
||||
do { \
|
||||
fprintf(stderr, args); \
|
||||
fprintf(stderr, "\n"); \
|
||||
} while (0)
|
||||
|
||||
uint64_t ntohll(uint64_t a) { return ((uint64_t)ntohl(a & 0xffffffff) << 32) | ntohl(a >> 32); }
|
||||
#define htonll ntohll
|
||||
|
||||
void readAll(int fd, void *dst, uint32_t length) {
|
||||
while (length) {
|
||||
int curr = read(fd, dst, length);
|
||||
if (curr < 0)
|
||||
FAIL("read failed on fd:%d", fd);
|
||||
length -= curr;
|
||||
dst = (char *)dst + curr;
|
||||
}
|
||||
}
|
||||
|
||||
void writeAll(int fd, void *dst, uint32_t length) {
|
||||
while (length) {
|
||||
int curr = write(fd, dst, length);
|
||||
if (curr < 0)
|
||||
FAIL("write failed on fd:%d", fd);
|
||||
length -= curr;
|
||||
dst = (char *)dst + curr;
|
||||
}
|
||||
}
|
||||
|
||||
int nbd;
|
||||
int sock;
|
||||
int sockets[2];
|
||||
struct nbd_request request;
|
||||
struct nbd_reply reply;
|
||||
|
||||
void nbd_ioctl(unsigned id, int arg) {
|
||||
int err = ioctl(nbd, id, arg);
|
||||
if (err < 0)
|
||||
FAIL("ioctl(%ud) failed [%s]", id, strerror(errno));
|
||||
}
|
||||
|
||||
void startclient() {
|
||||
close(sockets[0]);
|
||||
nbd_ioctl(NBD_SET_SOCK, sockets[1]);
|
||||
nbd_ioctl(NBD_DO_IT, 0);
|
||||
nbd_ioctl(NBD_CLEAR_QUE, 0);
|
||||
nbd_ioctl(NBD_CLEAR_SOCK, 0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#define dev_file "/dev/nbd0"
|
||||
|
||||
void handleread(int off, int len) {
|
||||
uint8_t buf[512];
|
||||
// fprintf(stderr, "read @%d len=%d\n", off, len);
|
||||
// htonl(EPERM);
|
||||
reply.error = 0;
|
||||
writeAll(sock, &reply, sizeof(struct nbd_reply));
|
||||
for (int i = 0; i < len; ++i) {
|
||||
read_block(off + i, buf);
|
||||
writeAll(sock, buf, 512);
|
||||
}
|
||||
}
|
||||
|
||||
void handlewrite(int off, int len) {
|
||||
uint8_t buf[512];
|
||||
// fprintf(stderr, "write @%d len=%d\n", off, len);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
readAll(sock, buf, 512);
|
||||
write_block(off + i, buf);
|
||||
}
|
||||
reply.error = 0;
|
||||
writeAll(sock, &reply, sizeof(struct nbd_reply));
|
||||
}
|
||||
|
||||
void setupFs();
|
||||
|
||||
void runNBD() {
|
||||
setupFs();
|
||||
|
||||
int err = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
|
||||
assert(err >= 0);
|
||||
|
||||
nbd = open(dev_file, O_RDWR);
|
||||
assert(nbd >= 0);
|
||||
|
||||
nbd_ioctl(BLKFLSBUF, 0);
|
||||
nbd_ioctl(NBD_SET_BLKSIZE, 512);
|
||||
nbd_ioctl(NBD_SET_SIZE_BLOCKS, NUM_BLOCKS);
|
||||
nbd_ioctl(NBD_CLEAR_SOCK, 0);
|
||||
|
||||
if (!fork())
|
||||
startclient();
|
||||
|
||||
int fd = open(dev_file, O_RDONLY);
|
||||
assert(fd != -1);
|
||||
close(fd);
|
||||
|
||||
close(sockets[1]);
|
||||
sock = sockets[0];
|
||||
|
||||
reply.magic = htonl(NBD_REPLY_MAGIC);
|
||||
reply.error = htonl(0);
|
||||
|
||||
for (;;) {
|
||||
nbd_ioctl(BLKFLSBUF, 0); // flush buffers - we don't want the kernel to cache the writes
|
||||
int nread = read(sock, &request, sizeof(request));
|
||||
|
||||
if (nread < 0) {
|
||||
FAIL("nbd read err %s", strerror(errno));
|
||||
}
|
||||
if (nread == 0)
|
||||
return;
|
||||
assert(nread == sizeof(request));
|
||||
memcpy(reply.handle, request.handle, sizeof(reply.handle));
|
||||
reply.error = htonl(0);
|
||||
|
||||
assert(request.magic == htonl(NBD_REQUEST_MAGIC));
|
||||
|
||||
uint32_t len = ntohl(request.len);
|
||||
assert((len & 511) == 0);
|
||||
len >>= 9;
|
||||
uint64_t from = ntohll(request.from);
|
||||
assert((from & 511) == 0);
|
||||
from >>= 9;
|
||||
|
||||
switch (ntohl(request.type)) {
|
||||
case NBD_CMD_READ:
|
||||
handleread(from, len);
|
||||
break;
|
||||
case NBD_CMD_WRITE:
|
||||
handlewrite(from, len);
|
||||
break;
|
||||
case NBD_CMD_DISC:
|
||||
return;
|
||||
default:
|
||||
FAIL("invalid cmd: %d", ntohl(request.type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void enableMSD(int enabled) {
|
||||
#ifndef X86
|
||||
int fd = open("/sys/devices/platform/musb_hdrc/gadget/lun0/active", O_WRONLY);
|
||||
write(fd, enabled ? "1" : "0", 1);
|
||||
close(fd);
|
||||
#else
|
||||
LOG("fake enable MSD: %d", enabled);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main() {
|
||||
#ifndef X86
|
||||
daemon(0, 1);
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
pid_t child = fork();
|
||||
if (child == 0) {
|
||||
runNBD();
|
||||
return 0;
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
enableMSD(1);
|
||||
|
||||
int wstatus = 0;
|
||||
waitpid(child, &wstatus, 0);
|
||||
enableMSD(0); // force "eject"
|
||||
|
||||
if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) {
|
||||
LOG("abnormal child return, %d", child);
|
||||
sleep(5);
|
||||
} else {
|
||||
sleep(2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
37
brick/uf2daemon/uf2.h
Normal file
37
brick/uf2daemon/uf2.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef UF2_H
|
||||
#define UF2_H 1
|
||||
|
||||
#include "uf2format.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef INDEX_URL
|
||||
#define INDEX_URL "https://www.pxt.io/"
|
||||
#endif
|
||||
|
||||
#define UF2_VERSION_BASE "v0.1.0"
|
||||
|
||||
// needs to be more than ~4200 and less than ~65000 (to force FAT16)
|
||||
#define NUM_FAT_BLOCKS 65000
|
||||
|
||||
#define UF2_VERSION UF2_VERSION_BASE " F"
|
||||
|
||||
//! Static block size for all memories
|
||||
#define UDI_MSC_BLOCK_SIZE 512L
|
||||
|
||||
void read_block(uint32_t block_no, uint8_t *data);
|
||||
|
||||
void write_block(uint32_t block_no, uint8_t *data);
|
||||
|
||||
#define CONCAT_1(a, b) a##b
|
||||
#define CONCAT_0(a, b) CONCAT_1(a, b)
|
||||
#define STATIC_ASSERT(e) \
|
||||
enum { CONCAT_0(_static_assert_, __LINE__) = 1 / ((e) ? 1 : 0) }
|
||||
|
||||
extern const char infoUf2File[];
|
||||
|
||||
void readAll(int fd, void *dst, uint32_t length);
|
||||
|
||||
STATIC_ASSERT(sizeof(UF2_Block) == 512);
|
||||
|
||||
#endif
|
48
brick/uf2daemon/uf2format.h
Normal file
48
brick/uf2daemon/uf2format.h
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef UF2FORMAT_H
|
||||
#define UF2FORMAT_H 1
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// All entries are little endian.
|
||||
|
||||
// if you increase that, you will also need to update the linker script file
|
||||
#define APP_START_ADDRESS 0x00002000
|
||||
|
||||
#define UF2_MAGIC_START0 0x0A324655UL // "UF2\n"
|
||||
#define UF2_MAGIC_START1 0x9E5D5157UL // Randomly selected
|
||||
#define UF2_MAGIC_END 0x0AB16F30UL // Ditto
|
||||
|
||||
// If set, the block is "comment" and should not be flashed to the device
|
||||
#define UF2_FLAG_NOFLASH 0x00000001
|
||||
#define UF2_FLAG_FILE 0x00001000
|
||||
#define UF2_FILENAME_MAX 150
|
||||
#define UF2_MAX_PAYLOAD (476 - 10) // leaving some space for filename
|
||||
// for this bootloader
|
||||
#define UF2_MAX_FILESIZE (64 * 1024 * 1024)
|
||||
|
||||
typedef struct {
|
||||
// 32 byte header
|
||||
uint32_t magicStart0;
|
||||
uint32_t magicStart1;
|
||||
uint32_t flags;
|
||||
uint32_t targetAddr;
|
||||
uint32_t payloadSize;
|
||||
uint32_t blockNo;
|
||||
uint32_t numBlocks;
|
||||
uint32_t fileSize;
|
||||
|
||||
// raw data, followed by filename (NUL-terminated) at payloadSize
|
||||
uint8_t data[476];
|
||||
|
||||
// store magic also at the end to limit damage from partial block reads
|
||||
uint32_t magicEnd;
|
||||
} UF2_Block;
|
||||
|
||||
static inline bool is_uf2_block(void *data) {
|
||||
UF2_Block *bl = (UF2_Block *)data;
|
||||
return bl->magicStart0 == UF2_MAGIC_START0 && bl->magicStart1 == UF2_MAGIC_START1 &&
|
||||
bl->magicEnd == UF2_MAGIC_END;
|
||||
}
|
||||
|
||||
#endif
|
106
brick/uf2daemon/uf2hid.h
Normal file
106
brick/uf2daemon/uf2hid.h
Normal file
@ -0,0 +1,106 @@
|
||||
#ifndef UF2_HID_H
|
||||
#define UF2_HID_H 1
|
||||
|
||||
#define HF2_CMD_BININFO 0x0001
|
||||
// no arguments
|
||||
#define HF2_MODE_BOOTLOADER 0x01
|
||||
#define HF2_MODE_USERSPACE 0x02
|
||||
struct HF2_BININFO_Result {
|
||||
uint32_t mode;
|
||||
uint32_t flash_page_size;
|
||||
uint32_t flash_num_pages;
|
||||
uint32_t max_message_size;
|
||||
};
|
||||
|
||||
#define HF2_CMD_INFO 0x0002
|
||||
// no arguments
|
||||
// results is utf8 character array
|
||||
|
||||
#define HF2_CMD_RESET_INTO_APP 0x0003
|
||||
// no arguments, no result
|
||||
|
||||
#define HF2_CMD_RESET_INTO_BOOTLOADER 0x0004
|
||||
// no arguments, no result
|
||||
|
||||
#define HF2_CMD_START_FLASH 0x0005
|
||||
// no arguments, no result
|
||||
|
||||
#define HF2_CMD_WRITE_FLASH_PAGE 0x0006
|
||||
struct HF2_WRITE_FLASH_PAGE_Command {
|
||||
uint32_t target_addr;
|
||||
uint32_t data[0];
|
||||
};
|
||||
// no result
|
||||
|
||||
#define HF2_CMD_CHKSUM_PAGES 0x0007
|
||||
struct HF2_CHKSUM_PAGES_Command {
|
||||
uint32_t target_addr;
|
||||
uint32_t num_pages;
|
||||
};
|
||||
struct HF2_CHKSUM_PAGES_Result {
|
||||
uint16_t chksums[0 /* num_pages */];
|
||||
};
|
||||
|
||||
#define HF2_CMD_READ_WORDS 0x0008
|
||||
struct HF2_READ_WORDS_Command {
|
||||
uint32_t target_addr;
|
||||
uint32_t num_words;
|
||||
};
|
||||
struct HF2_READ_WORDS_Result {
|
||||
uint32_t words[0 /* num_words */];
|
||||
};
|
||||
|
||||
#define HF2_CMD_WRITE_WORDS 0x0009
|
||||
struct HF2_WRITE_WORDS_Command {
|
||||
uint32_t target_addr;
|
||||
uint32_t num_words;
|
||||
uint32_t words[0 /* num_words */];
|
||||
};
|
||||
// no result
|
||||
|
||||
#define HF2_CMD_DMESG 0x0010
|
||||
// no arguments
|
||||
// results is utf8 character array
|
||||
|
||||
typedef struct {
|
||||
uint32_t command_id;
|
||||
uint16_t tag;
|
||||
uint8_t reserved0;
|
||||
uint8_t reserved1;
|
||||
|
||||
union {
|
||||
struct HF2_WRITE_FLASH_PAGE_Command write_flash_page;
|
||||
struct HF2_WRITE_WORDS_Command write_words;
|
||||
struct HF2_READ_WORDS_Command read_words;
|
||||
struct HF2_CHKSUM_PAGES_Command chksum_pages;
|
||||
};
|
||||
} HF2_Command;
|
||||
|
||||
typedef struct {
|
||||
uint16_t tag;
|
||||
union {
|
||||
struct {
|
||||
uint8_t status;
|
||||
uint8_t status_info;
|
||||
};
|
||||
uint16_t status16;
|
||||
};
|
||||
union {
|
||||
struct HF2_BININFO_Result bininfo;
|
||||
uint8_t data8[0];
|
||||
uint16_t data16[0];
|
||||
uint32_t data32[0];
|
||||
};
|
||||
} HF2_Response;
|
||||
|
||||
#define HF2_FLAG_SERIAL_OUT 0x80
|
||||
#define HF2_FLAG_SERIAL_ERR 0xC0
|
||||
#define HF2_FLAG_CMDPKT_LAST 0x40
|
||||
#define HF2_FLAG_CMDPKT_BODY 0x00
|
||||
#define HF2_FLAG_MASK 0xC0
|
||||
#define HF2_SIZE_MASK 63
|
||||
|
||||
#define HF2_STATUS_OK 0x00
|
||||
#define HF2_STATUS_INVALID_CMD 0x01
|
||||
|
||||
#endif
|
19
cmds/cmds.ts
Normal file
19
cmds/cmds.ts
Normal file
@ -0,0 +1,19 @@
|
||||
/// <reference path="../node_modules/pxt-core/typings/globals/node/index.d.ts"/>
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtlib.d.ts" />
|
||||
|
||||
import * as fs from 'fs';
|
||||
|
||||
require("./editor")
|
||||
|
||||
declare namespace pxt.editor {
|
||||
function deployCoreAsync(resp: pxtc.CompileResult, disconnect?: boolean): Promise<void>;
|
||||
}
|
||||
|
||||
export function deployCoreAsync(resp: pxtc.CompileResult) {
|
||||
return pxt.editor.deployCoreAsync(resp, process.env["PXT_SERIAL"] ? false : true)
|
||||
.then(() => {
|
||||
fs.writeFileSync("built/full-" + pxtc.BINARY_UF2, resp.outfiles[pxtc.BINARY_UF2], {
|
||||
encoding: "base64"
|
||||
})
|
||||
})
|
||||
}
|
7
cmds/pxtrequire.ts
Normal file
7
cmds/pxtrequire.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/// <reference path="../node_modules/pxt-core/typings/globals/node/index.d.ts"/>
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtlib.d.ts" />
|
||||
|
||||
import * as path from "path";
|
||||
export let pxtCore = require("pxt-core");
|
||||
// require.resolve() gives path to [pxt dir]/built/pxt.js, so move up twice to get pxt root dir
|
||||
export let pxtCoreDir = path.resolve(require.resolve("pxt-core"), "..", "..");
|
@ -3,9 +3,11 @@
|
||||
"target": "es5",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"declaration": true,
|
||||
"outDir": "../built",
|
||||
"module": "commonjs",
|
||||
"rootDir": ".",
|
||||
"newLine": "LF",
|
||||
"sourceMap": false,
|
||||
"types": []
|
||||
"sourceMap": false
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
<footer class="ui vertical footer segment hideprint" aria-hidden="false">
|
||||
<div class="ui center aligned container">
|
||||
<div class="ui section divider"></div>
|
||||
<div class="ui container horizontal small divided link list">
|
||||
<!-- <a class="item" href="https://makecode.com/contact" target="_blank" rel="noopener">Contact Us</a> -->
|
||||
<a class="item" href="https://makecode.com/privacy" target="_blank" rel="noopener">Privacy & Cookies</a>
|
||||
<a class="item" href="https://makecode.com/termsofuse" target="_blank" rel="noopener"> Terms Of Use</a>
|
||||
<a class="item" href="https://makecode.com/trademarks" target="_blank" rel="noopener">Trademarks</a>
|
||||
<div class="item">© 2018 Microsoft</div>
|
||||
</div>
|
||||
<div class="ui container horizontal small divided link list">
|
||||
<a class="ui centered item" href="https://makecode.com/" title="Microsoft MakeCode" target="_blank" rel="noopener">Powered by Microsoft MakeCode</a>
|
||||
</div>
|
||||
<div class="ui centered container small list">
|
||||
<p class="item">LEGO, the LEGO logo, MINDSTORMS and the MINDSTORMS EV3 logo are trademarks and/ or copyrights of the LEGO Group. ©2018 The LEGO Group. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
@ -1 +0,0 @@
|
||||
<meta name="robots" content="noindex">
|
136
docs/SUMMARY.md
136
docs/SUMMARY.md
@ -1,135 +1,11 @@
|
||||
# @extends
|
||||
|
||||
## Support #support
|
||||
|
||||
* [Troubleshoot](/troubleshoot)
|
||||
* [EV3 Manager](https://ev3manager.education.lego.com/)
|
||||
* [Bluetooth](/bluetooth)
|
||||
* [Forum](https://forum.makecode.com)
|
||||
* [LEGO Support](https://www.lego.com/service/)
|
||||
* [FIRST LEGO League](/fll)
|
||||
|
||||
## Projects #projects
|
||||
|
||||
* [Getting Started](/getting-started)
|
||||
* [Try](/getting-started/try)
|
||||
* [Use](/getting-started/use)
|
||||
|
||||
* [Tutorials](/tutorials)
|
||||
* [Wake Up!](/tutorials/wake-up)
|
||||
* [Make An Animation](/tutorials/make-an-animation)
|
||||
* [What Animal Am I?](/tutorials/what-animal-am-i)
|
||||
* [Music Brick](/tutorials/music-brick)
|
||||
* [Run Motors](/tutorials/run-motors)
|
||||
* [Tank ZigZag](/tutorials/tank-zigzag)
|
||||
* [Touch to Run](/tutorials/touch-to-run)
|
||||
* [Touch Sensor Values](/tutorials/touch-sensor-values)
|
||||
* [What Color?](/tutorials/what-color)
|
||||
* [Line Following](/tutorials/line-following)
|
||||
* [Red Light, Green Light](/tutorials/redlight-greenlight)
|
||||
* [Reflected Light Measure](/tutorials/reflected-light-measure)
|
||||
* [Reflected Light Calibration](/tutorials/reflected-light-calibration)
|
||||
* [Object Near?](/tutorials/object-near)
|
||||
* [Security Alert](/tutorials/security-alert)
|
||||
|
||||
* [Coding](/coding)
|
||||
* [Autonomous Parking](/coding/autonomous-parking)
|
||||
* [Object Detection](/coding/object-detection)
|
||||
* [Line Detection](/coding/line-detection)
|
||||
|
||||
* [Design Engineering](/design-engineering)
|
||||
* [Make It Move Without Wheels](/design-engineering/make-it-move)
|
||||
* [Make It Smarter and Faster](/design-engineering/make-it-smarter)
|
||||
* [Make a System that Communicates](/design-engineering/make-it-communicate)
|
||||
|
||||
* [Maker](/maker)
|
||||
* [Make a Sound Machine](/maker/sound-machine)
|
||||
* [Make a Security Gadget](/maker/security-gadget)
|
||||
|
||||
## Reference #reference
|
||||
|
||||
* [Reference](/reference)
|
||||
* [Brick](/reference/brick)
|
||||
* [show string](/reference/brick/show-string)
|
||||
* [show number](/reference/brick/show-number)
|
||||
* [show value](/reference/brick/show-value)
|
||||
* [show mood](/reference/brick/show-mood)
|
||||
* [show image](/reference/brick/show-image)
|
||||
* [clear screen](/reference/brick/clear-screen)
|
||||
* [show ports](/reference/brick/show-ports)
|
||||
* [on event](/reference/brick/button/on-event)
|
||||
* [is pressed](/reference/brick/button/is-pressed)
|
||||
* [was pressed](/reference/brick/button/was-pressed)
|
||||
* [pause until](/reference/brick/button/pause-until)
|
||||
* [set light](/reference/brick/set-status-light)
|
||||
* [battery level](/reference/brick/battery-level)
|
||||
* [Motors](/reference/motors)
|
||||
* [run](/reference/motors/motor/run)
|
||||
* [stop](/reference/motors/motor/stop)
|
||||
* [reset](/reference/motors/motor/reset)
|
||||
* [set brake](/reference/motors/motor/set-brake)
|
||||
* [set inverted](/reference/motors/motor/set-inverted)
|
||||
* [set regulated](/reference/motors/motor/set-regulated)
|
||||
* [tank](/reference/motors/synced/tank)
|
||||
* [steer](/reference/motors/synced/steer)
|
||||
* [angle](/reference/motors/motor/angle)
|
||||
* [speed](/reference/motors/motor/speed)
|
||||
* [clear counts](/reference/motors/motor/clear-counts)
|
||||
* [stop all motors](/reference/motors/stop-all)
|
||||
* [Sensors](/reference/sensors)
|
||||
* [Touch](/reference/sensors/touch-sensor)
|
||||
* [on event](/reference/sensors/touch-sensor/on-event)
|
||||
* [pause until](/reference/sensors/touch-sensor/pause-until)
|
||||
* [is pressed](/reference/sensors/touch-sensor/is-pressed)
|
||||
* [was pressed](/reference/sensors/touch-sensor/was-pressed)
|
||||
* [Gyro](/reference/sensors/gyro)
|
||||
* [angle](/reference/sensors/gyro/angle)
|
||||
* [rate](/reference/sensors/gyro/rate)
|
||||
* [reset](/reference/sensors/gyro/reset)
|
||||
* [Ultrasonic](/reference/sensors/ultrasonic)
|
||||
* [on event](/reference/sensors/ultrasonic/on-event)
|
||||
* [distance](/reference/sensors/ultrasonic/distance)
|
||||
* [pause until](/reference/sensors/ultrasonic/pause-until)
|
||||
* [Infrared](/reference/sensors/infrared)
|
||||
* [on event](/reference/sensors/infrared/on-event)
|
||||
* [distance](/reference/sensors/infrared/proximity)
|
||||
* [pause until](/reference/sensors/infrared/pause-until)
|
||||
* [Infrared beacon](/reference/sensors/beacon)
|
||||
* [on event](/reference/sensors/beacon/on-event)
|
||||
* [pause until](/reference/sensors/beacon/pause-until)
|
||||
* [is pressed](/reference/sensors/beacon/is-pressed)
|
||||
* [was pressed](/reference/sensors/beacon/was-pressed)
|
||||
* [set remote channel](/reference/sensors/beacon/set-remote-channel)
|
||||
* [Color](/reference/sensors/color-sensor)
|
||||
* [on color detected](/reference/sensors/color-sensor/on-color-detected)
|
||||
* [pause until color detected](/reference/sensors/color-sensor/pause-until-color-detected)
|
||||
* [on light detected](/reference/sensors/color-sensor/on-light-detected)
|
||||
* [pause until light condition detected](/reference/sensors/color-sensor/pause-until-light-detected)
|
||||
* [color](/reference/sensors/color-sensor/color)
|
||||
* [light](/reference/sensors/color-sensor/ambient-light)
|
||||
* [Music](/reference/music)
|
||||
* [play sound effect](/reference/music/play-sound-effect)
|
||||
* [play sound effect until done](/reference/music/play-sound-effect-until-done)
|
||||
* [play tone](/reference/music/play-tone)
|
||||
* [ring tone](/reference/music/ring-tone)
|
||||
* [stop all sounds](/reference/music/stop-all-sounds)
|
||||
* [rest](/reference/music/rest)
|
||||
* [change tempo by](/reference/music/change-tempo-by)
|
||||
* [set tempo](/reference/music/set-tempo)
|
||||
* [note frequency](/reference/music/note-frequency)
|
||||
* [beat](/reference/music/beat)
|
||||
* [set volume](/reference/music/set-volume)
|
||||
* [Control](/reference/control)
|
||||
* [Timer](/reference/control/timer)
|
||||
* [seconds](/reference/control/timer/seconds)
|
||||
* [millis](/reference/control/timer/millis)
|
||||
* [reset](/reference/control/timer/reset)
|
||||
* [pause until](/reference/control/timer/pause-until)
|
||||
* [Console](/reference/console)
|
||||
* [log](/reference/console/log)
|
||||
* [log value](/reference/console/log-value)
|
||||
* [send to screen](/reference/console/send-to-screen)
|
||||
|
||||
## #misc
|
||||
|
||||
## devs
|
||||
* [input](/reference/input)
|
||||
* [light](/reference/light)
|
||||
* [music](/reference/music)
|
||||
* [pins](/reference/pins)
|
||||
* [control](/reference/control)
|
||||
* [serial](/reference/serial)
|
||||
|
@ -6,52 +6,38 @@ Welcome to the **Microsoft MakeCode** editor for the **@boardname@**!
|
||||
|
||||
You can program the @boardname@ using [Blocks](/blocks) or [JavaScript](/javascript) in your web browser:
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Bumped, () => {
|
||||
motors.largeA.run(50)
|
||||
```block
|
||||
input.buttonA.onEvent(ButtonEvent.Click, () => {
|
||||
light.showRing(`blue blue blue blue blue blue blue blue blue blue`)
|
||||
})
|
||||
```
|
||||
```typescript
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Bumped, () => {
|
||||
motors.largeA.run(50)
|
||||
input.buttonA.onEvent(ButtonEvent.Click, () => {
|
||||
light.showRing(`blue blue blue blue blue blue blue blue blue blue`)
|
||||
})
|
||||
```
|
||||
|
||||
The editor works in [most modern browsers](/browsers). It works [offline](/offline) once loaded and doesn't require any installation. Take a look at some of the [features](/about/editor-features) of the editor.
|
||||
The editor work in [most modern browsers](/browsers), work [offline](/offline) once loaded and do not require any installation.
|
||||
|
||||
### ~ hint
|
||||
## [Compile and Flash: Your Program!](/device/usb)
|
||||
|
||||
#### Using LEGO® MINDSTORMS® Education NXT
|
||||
|
||||
The MakeCode editor works with @boardname@. To create code for LEGO® MINDSTORMS® Education NXT, you need to [download](https://education.lego.com/downloads/retiredproducts/nxt/software) the software to program it.
|
||||
|
||||
### ~
|
||||
|
||||
## Compile and Flash: Your Program!
|
||||
|
||||
When you have your code ready, you connect your EV3 Brick to a computer with a USB cable so it appears as an attached drive (named **@drivename@**).
|
||||
When you have your code ready, you connect your @boardname@ to a computer via a USB cable
|
||||
**then press the reset button** so it appears as a mounted drive (named **CPLAYBOOT**).
|
||||
|
||||
Compilation to machine code from [Blocks](/blocks) or [JavaScript](/javascript) happens in the browser. You save the binary
|
||||
program to a **.uf2** file, which you then copy to the **@drivename@** drive. The process of copying will flash the device with the new program.
|
||||
|
||||
### ~ hint
|
||||
|
||||
#### Bluetooth support
|
||||
|
||||
**Experimental support** for Bluetooth download is now available. Please read the [Bluetooth](/bluetooth) page for more information.
|
||||
|
||||
### ~
|
||||
program to a **.uf2** file, which you then copy to the **CPLAYBOOT** drive, which flashes the device with the new program.
|
||||
|
||||
## Simulator: Test Your Code
|
||||
|
||||
You can run your code using the @boardname@ simulator, all inside the same browser window.
|
||||
The simulator has support for the EV3 Brick screen, buttons, sensors, and motors.
|
||||
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
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Bumped, () => {
|
||||
motors.largeA.run(50)
|
||||
motors.mediumD.run(50)
|
||||
sensors.touch1.pauseUntil(ButtonEvent.Pressed)
|
||||
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectDetected)
|
||||
loops.forever(() => {
|
||||
light.pixels.showAnimation(light.animation(LightAnimation.Rainbow), 1000)
|
||||
})
|
||||
```
|
||||
```
|
||||
|
||||
```package
|
||||
light
|
||||
```
|
||||
|
@ -1,81 +0,0 @@
|
||||
# @extends
|
||||
|
||||
#### #blocks-images
|
||||
|
||||
| |
|
||||
|-|
|
||||
| ![Blocks Toolbox with Loops shelf open](/static/about/blocks-toolbox.png) |
|
||||
| Blocks Toolbox |
|
||||
|
||||
#### #home-images
|
||||
|
||||
| |
|
||||
|-|
|
||||
| ![Home button](/static/about/home-button.png) |
|
||||
| Home Button |
|
||||
|
||||
#### #share-images
|
||||
|
||||
| |
|
||||
|-|
|
||||
| ![Share button](/static/about/share-button.png) |
|
||||
| Share Button |
|
||||
|
||||
#### #blocksjs-images
|
||||
|
||||
| |
|
||||
|-|
|
||||
| ![Switch from Blocks to JavaScript](/static/about/blocks-to-js.gif) |
|
||||
| Switch from Blocks to JavaScript |
|
||||
|
||||
#### #help-images
|
||||
|
||||
| |
|
||||
|-|
|
||||
| ![Help button](/static/about/help-button.png) |
|
||||
| Help Button |
|
||||
|
||||
#### #moresettings-images
|
||||
|
||||
| |
|
||||
|-|
|
||||
| ![More settings button](/static/about/more-settings.png) |
|
||||
| More Button |
|
||||
|
||||
#### #undoredo-images
|
||||
|
||||
| | | |
|
||||
|-|-|-|
|
||||
| ![Undo button](/static/about/undo-button.png) | | ![Redo button](/static/about/redo-button.png) |
|
||||
| Undo Button | | Redo Button |
|
||||
|
||||
#### #zoom-images
|
||||
|
||||
| | | |
|
||||
|-|-|-|
|
||||
| ![Zoom in button](/static/about/zoom-in.png) | | ![Zoom out button](/static/about/zoom-out.png) |
|
||||
| Zoom In | | Zoom Out |
|
||||
|
||||
#### #saveproject-images
|
||||
|
||||
| |
|
||||
|-|
|
||||
| ![Save project field](/static/about/save-project.png) |
|
||||
| Save Project |
|
||||
|
||||
#### #download-images
|
||||
|
||||
| |
|
||||
|-|
|
||||
| ![Download button](/static/about/download-button.png) |
|
||||
| Download Button |
|
||||
|
||||
#### #explorer-images
|
||||
|
||||
| |
|
||||
|-|
|
||||
| ![Explorer button](/static/about/explorer-button.png) |
|
||||
| Explorer Button |
|
||||
| |
|
||||
| ![Explorer File View](/static/about/explorer-view.png) |
|
||||
| Explorer File View |
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"appref": "v1.4"
|
||||
"appref": "v"
|
||||
}
|
||||
|
@ -3,6 +3,6 @@
|
||||
### #specific
|
||||
|
||||
```cards
|
||||
forever(() => {});
|
||||
pause(0)
|
||||
loops.forever(() => {});
|
||||
loops.pause(0)
|
||||
```
|
@ -1,62 +0,0 @@
|
||||
# Bluetooth
|
||||
|
||||
This page describes the procedure to download MakeCode program to the EV3 brick
|
||||
over Bluetooth.
|
||||
|
||||
## ~ hint
|
||||
|
||||
### WARNING: EXPERIMENTAL FEATURES AHEAD!
|
||||
|
||||
Support for Bluetooth download relies on [Web Serial](https://wicg.github.io/serial/),
|
||||
an experimental browser feature. Web Serial is a work [in progress](https://www.chromestatus.com/feature/6577673212002304);
|
||||
it may change or be removed in future versions without notice.
|
||||
|
||||
By enabling these experimental browser features, you could lose browser data or compromise your device security
|
||||
or privacy.
|
||||
|
||||
## ~
|
||||
|
||||
https://youtu.be/VIq8-6Egtqs
|
||||
|
||||
## Supported browsers
|
||||
|
||||
* Chrome desktop, version 77 and higher, Windows 10 or Mac OS.
|
||||
* [Microsoft Edge Insider desktop](https://www.microsoftedgeinsider.com), version 77 and higher, Windows 10 or Mac OS.
|
||||
|
||||
To make sure your browser is up to date, go to the '...' menu, click "Help" then "About".
|
||||
|
||||
Next you need to enable the experimental features (this may change in the future)
|
||||
|
||||
* go to **chrome://flags/#enable-experimental-web-platform-features** and **enable**
|
||||
**Experimental Web Platform features**
|
||||
|
||||
![A screenshot of the flags page in chrome](/static/bluetooth/experimental.png)
|
||||
|
||||
## Machine Setup
|
||||
|
||||
* pair your EV3 brick with your computer over Bluetooth. This is the usual pairing procedure.
|
||||
|
||||
## Download over Bluetooth
|
||||
|
||||
* go to https://makecode.mindstorms.com/
|
||||
* click on **Download** to start a file download as usual
|
||||
* on the download dialog, you should see a **Bluetooth** button. Click on the
|
||||
**Bluetooth** button to enable the mode.
|
||||
* **make sure the EV3 brick is not running a program**
|
||||
* click on **Download** again to download over bluetooth.
|
||||
|
||||
## Choosing the correct serial port
|
||||
|
||||
Unfortunately, the browser dialog does not make it easy to select which serial port is the brick.
|
||||
|
||||
* On Windows, choose ``Standard Serial over Bluetooth``. There might be multiple of those but only one works. Try your luck! Once you know the COM port number, remember it for the next time around.
|
||||
* On Mac OS, choose ``cu.BRICKNAME-SerialPort``
|
||||
|
||||
## Known issues
|
||||
|
||||
* We do not detect properly that the program is running on the brick. Make sure to stop the program before starting the download procedure.
|
||||
* The list of programs on the brick screen is not updated when uploading via bluetooth.
|
||||
|
||||
## Feedback
|
||||
|
||||
Please send us your feedback through https://forum.makecode.com.
|
@ -1,27 +0,0 @@
|
||||
# Coding Activites
|
||||
|
||||
|
||||
## Projects
|
||||
|
||||
```codecard
|
||||
[
|
||||
{
|
||||
"name": "Autonomous Parking",
|
||||
"description": "Design cars that can park themselves safely without driver intervention.",
|
||||
"url":"/coding/autonomous-parking",
|
||||
"imageUrl": "/static/lessons/autonomous-parking.png",
|
||||
"cardType": "side"
|
||||
}, {
|
||||
"name": "Object Detection",
|
||||
"description": "Design ways to avoid accidents between vehicles and objects in the road.",
|
||||
"url":"/coding/object-detection",
|
||||
"imageUrl": "/static/lessons/object-detection.jpg",
|
||||
"cardType": "side"
|
||||
}, {
|
||||
"name": "Line Detection",
|
||||
"description": "Design ways to improve driving safety by helping to prevent drivers from falling asleep and causing an accident.",
|
||||
"url":"/coding/line-detection",
|
||||
"imageUrl": "/static/lessons/line-detection.jpg",
|
||||
"cardType": "side"
|
||||
}]
|
||||
```
|
@ -1,177 +0,0 @@
|
||||
# Autonomous Parking
|
||||
|
||||
Design cars that can park themselves safely without driver intervention.
|
||||
|
||||
![Autonomous parking graphic](/static/coding/autonomous-parking/auto-parking-connect.jpg)
|
||||
|
||||
## Connect
|
||||
|
||||
**Think about:**
|
||||
|
||||
* How do autonomous cars work?
|
||||
* What would it take to ensure that autonomous cars are safe?
|
||||
* What types of movements do autonomous cars need to perform?
|
||||
|
||||
## Construct
|
||||
|
||||
### Build
|
||||
|
||||
Build a @boardname@ vehicle that can park itself safely without driver intervention. Start by constructing this model:
|
||||
|
||||
[![EV3- Robot Driving Base](/static/coding/autonomous-parking/ev3-robot-driving-base.jpg)](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf)
|
||||
|
||||
### ~hint
|
||||
|
||||
If clicking the above image doesn't open the instructions, right-click on the image and choose "Save link as..." to download the PDF.
|
||||
|
||||
### ~
|
||||
|
||||
### Check
|
||||
|
||||
Before you program, check:
|
||||
|
||||
* Are all the wires correctly connected from the motors to ports B and C?
|
||||
* Are the wheels correctly installed?
|
||||
* Are the wheels rotating freely?
|
||||
|
||||
### Program
|
||||
|
||||
Write a program that will make the robot turn three times in various ways.
|
||||
|
||||
**Think about:**
|
||||
|
||||
* How will you make the robot turn in different ways?
|
||||
* How can the robot make a three point turn?
|
||||
|
||||
### ~hint
|
||||
|
||||
Consider using these blocks in your solution:
|
||||
|
||||
```block
|
||||
motors.largeBC.tank(50, 50)
|
||||
pause(500)
|
||||
```
|
||||
|
||||
### ~
|
||||
|
||||
### Sample Solution - Three Point Turn
|
||||
|
||||
1. When the brick button is pressed, turn the driving base right and stop after 1.5 seconds.
|
||||
2. Turn the driving base left and stop after 1 second.
|
||||
3. Move the driving base forward for 3 seconds.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
motors.largeBC.tank(75, 30)
|
||||
loops.pause(1500)
|
||||
motors.largeBC.tank(-30, -75)
|
||||
loops.pause(1000)
|
||||
motors.largeBC.tank(50, 50)
|
||||
loops.pause(3000)
|
||||
})
|
||||
```
|
||||
|
||||
### Download and test
|
||||
|
||||
Click Download and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
## Contemplate
|
||||
|
||||
Choose one of the following autonomous driving scenarios and create a program for it:
|
||||
|
||||
* Parallel parking
|
||||
* Angle parking
|
||||
* Perpendicular parking
|
||||
|
||||
### ~hint
|
||||
|
||||
Document pseudocode for your program before choosing programming blocks.
|
||||
|
||||
### ~
|
||||
|
||||
### Sample Solution - Parallel Parking
|
||||
|
||||
1. When the brick button is pressed, drive forward in a straight line for 3 rotations.
|
||||
2. Wait for 1 second.
|
||||
3. Reverse motor rotation while turning for 1.5 rotations.
|
||||
4. Reverse motor rotation while turning the other way for 1.5 rotations.
|
||||
5. Drive backward in a straight line for 0.5 rotations.
|
||||
6. Drive forward in a straight line for 0.5 rotations.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
motors.largeBC.steer(0, 50, 3, MoveUnit.Rotations)
|
||||
pause(1000)
|
||||
motors.largeBC.steer(-50, -50, 1.5, MoveUnit.Rotations)
|
||||
motors.largeBC.steer(50, -50, 1.5, MoveUnit.Rotations)
|
||||
motors.largeBC.steer(0, -50, 0.5, MoveUnit.Rotations)
|
||||
motors.largeBC.steer(0, 50, 0.5, MoveUnit.Rotations)
|
||||
})
|
||||
```
|
||||
|
||||
### Download and test
|
||||
|
||||
Click Download and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
### Differentiation
|
||||
|
||||
Create a program that simulates displaying appropriate warning lights while parking.
|
||||
|
||||
### ~hint
|
||||
|
||||
Consider using this block in your solution:
|
||||
|
||||
```block
|
||||
brick.setStatusLight(StatusLight.OrangeFlash)
|
||||
```
|
||||
|
||||
### ~
|
||||
|
||||
### Sample Solution - Simulating Reverse Gear and Reverse Warning Lights
|
||||
|
||||
1. When the brick button is pressed, drive forward in a straight line for 3 rotations.
|
||||
2. Wait for 1 second.
|
||||
3. Set brick status light to orange flash.
|
||||
4. Reverse motor rotation while turning for 1.5 rotations.
|
||||
5. Reverse motor rotation while turning the other way for 1.5 rotations.
|
||||
6. Drive backward in a straight line for 0.5 rotations.
|
||||
7. Set brick status light to off.
|
||||
8. Drive forward in a straight line for 0.5 rotations.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
motors.largeBC.steer(0, 50, 3, MoveUnit.Rotations)
|
||||
pause(1000)
|
||||
brick.setStatusLight(StatusLight.OrangeFlash)
|
||||
motors.largeBC.steer(-50, -50, 1.5, MoveUnit.Rotations)
|
||||
motors.largeBC.steer(50, -50, 1.5, MoveUnit.Rotations)
|
||||
motors.largeBC.steer(0, -50, 0.5, MoveUnit.Rotations)
|
||||
brick.setStatusLight(StatusLight.Off)
|
||||
motors.largeBC.steer(0, 50, 0.5, MoveUnit.Rotations)
|
||||
})
|
||||
```
|
||||
|
||||
### Download and test
|
||||
|
||||
Click Download and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
### Share
|
||||
|
||||
**Think about:**
|
||||
|
||||
* What challenged you?
|
||||
* Were there any surprises?
|
||||
* How can you improve your program?
|
||||
* Can your program be more streamlined? Have you used too many blocks?
|
||||
* Is there a more efficient way to build your program?
|
||||
* How can your program be used in real-world scenarios?
|
||||
|
||||
## Continue
|
||||
|
||||
* Click on the JavaScript tab and experiment with changing the values in the code.
|
||||
* Add a custom image or sounds from the Brick or Music menus.
|
||||
* Create a video of your project, especially your final presentation and your robot’s performance. Explain some important features of your software program.
|
||||
* Include an image of your program with comments.
|
||||
* Add a team photograph!
|
||||
|
||||
Congratulations! What will you design next?
|
@ -1,65 +0,0 @@
|
||||
# Cruise Control
|
||||
|
||||
Learn how to set and adjust motor speeds.
|
||||
|
||||
## Activity 1
|
||||
|
||||
Increase motor speed when touch sensor `1` is pressed.
|
||||
|
||||
```blocks
|
||||
let speed = 0;
|
||||
sensors.touch1.onEvent(ButtonEvent.Pressed, function () {
|
||||
if (speed < 100)
|
||||
speed = speed + 10;
|
||||
motors.largeBC.run(speed);
|
||||
})
|
||||
```
|
||||
|
||||
## Activity 2
|
||||
|
||||
Add a "reduce" motor speed action when touch sensor `2` is pressed.
|
||||
|
||||
```blocks
|
||||
let speed = 0;
|
||||
sensors.touch1.onEvent(ButtonEvent.Pressed, function () {
|
||||
if (speed < 100)
|
||||
speed = speed + 10;
|
||||
motors.largeBC.run(speed);
|
||||
})
|
||||
sensors.touch2.onEvent(ButtonEvent.Pressed, function () {
|
||||
if (speed > -100)
|
||||
speed = speed - 10;
|
||||
motors.largeBC.run(speed);
|
||||
})
|
||||
```
|
||||
|
||||
## Activity 3
|
||||
|
||||
Refactor your code by moving the speed increase and speed decrease code into ``||functions:accelerate||`` and ``||functions:decelerate||`` functions. Run the motors at the new speed in an ``||functions:update||`` function.
|
||||
|
||||
```blocks
|
||||
let speed = 0
|
||||
function decelerate() {
|
||||
if (speed > -100) {
|
||||
speed = speed - 10
|
||||
}
|
||||
}
|
||||
function accelerate() {
|
||||
if (speed < 100) {
|
||||
speed = speed + 10
|
||||
}
|
||||
}
|
||||
function update() {
|
||||
brick.clearScreen()
|
||||
brick.showString("speed: " + speed, 1)
|
||||
motors.largeBC.run(speed)
|
||||
}
|
||||
sensors.touch2.onEvent(ButtonEvent.Pressed, function () {
|
||||
accelerate()
|
||||
update()
|
||||
})
|
||||
sensors.touch1.onEvent(ButtonEvent.Pressed, function () {
|
||||
decelerate()
|
||||
update()
|
||||
})
|
||||
```
|
@ -1,46 +0,0 @@
|
||||
# Ignition
|
||||
|
||||
Explore sensor events and sensor status.
|
||||
|
||||
## Activity 1
|
||||
|
||||
Wait for a touch sensor press or ultrasonic object detection. Show an expression on the screen when they happen.
|
||||
|
||||
```blocks
|
||||
sensors.touch1.onEvent(ButtonEvent.Pressed, function () {
|
||||
brick.showImage(images.eyesDizzy)
|
||||
})
|
||||
sensors.ultrasonic4.onEvent(UltrasonicSensorEvent.ObjectDetected, function () {
|
||||
brick.showImage(images.eyesTiredMiddle)
|
||||
})
|
||||
brick.showImage(images.eyesSleeping)
|
||||
```
|
||||
|
||||
## Activity 2
|
||||
|
||||
Play some motor sounds if touch sensor `1` is pressed at the same moment when and object comes close.
|
||||
|
||||
```blocks
|
||||
while (true) {
|
||||
if (sensors.touch1.isPressed() &&
|
||||
sensors.ultrasonic4.distance() < 10) {
|
||||
music.playSoundEffectUntilDone(sounds.mechanicalMotorStart)
|
||||
music.playSoundEffectUntilDone(sounds.mechanicalMotorIdle);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Activity 3
|
||||
|
||||
Play some motor sounds if touch sensor `1` is pressed when both the `enter` button is pressed on the brick and an object comes close.
|
||||
|
||||
```blocks
|
||||
while (true) {
|
||||
if (sensors.ultrasonic4.distance() < 10 &&
|
||||
sensors.touch1.isPressed() &&
|
||||
brick.buttonEnter.isPressed()) {
|
||||
music.playSoundEffectUntilDone(sounds.mechanicalMotorStart)
|
||||
music.playSoundEffectUntilDone(sounds.mechanicalMotorIdle);
|
||||
}
|
||||
}
|
||||
```
|
@ -1,9 +0,0 @@
|
||||
# Light the way Activity 1
|
||||
|
||||
```blocks
|
||||
sensors.color3.onLightDetected(LightIntensityMode.Ambient, Light.Dark, function () {
|
||||
brick.showImage(images.objectsLightOn)
|
||||
pause(5000)
|
||||
brick.clearScreen()
|
||||
})
|
||||
```
|
@ -1,10 +0,0 @@
|
||||
# Light the way Activity 2
|
||||
|
||||
```blocks
|
||||
sensors.color3.onLightDetected(LightIntensityMode.Ambient, Light.Bright, function () {
|
||||
brick.clearScreen()
|
||||
})
|
||||
sensors.color3.onLightDetected(LightIntensityMode.Ambient, Light.Dark, function () {
|
||||
brick.showImage(images.objectsLightOn)
|
||||
})
|
||||
```
|
@ -1,13 +0,0 @@
|
||||
# Light the way Activity 3
|
||||
|
||||
```blocks
|
||||
sensors.color3.onLightDetected(LightIntensityMode.Ambient, Light.Bright, function () {
|
||||
brick.clearScreen()
|
||||
})
|
||||
sensors.color3.onLightDetected(LightIntensityMode.Ambient, Light.Dark, function () {
|
||||
brick.showImage(images.objectsLightOn)
|
||||
})
|
||||
sensors.touch1.onEvent(ButtonEvent.Pressed, function () {
|
||||
brick.showImage(images.objectsLightOn);
|
||||
})
|
||||
```
|
@ -1,241 +0,0 @@
|
||||
# Line Detection
|
||||
|
||||
Design ways to improve driving safety by helping to prevent drivers from falling asleep and causing an accident.
|
||||
|
||||
![Car following the line on the road](/static/coding/line-detection/car-road-line.jpg)
|
||||
|
||||
## Connect
|
||||
|
||||
Think about:
|
||||
|
||||
* How can autonomous cars react to different traffic light signals?
|
||||
* What can happen if a driver falls asleep while driving?
|
||||
* How can we detect when a driver is falling asleep?
|
||||
|
||||
## Construct
|
||||
|
||||
### Build
|
||||
|
||||
Build a @boardname@ vehicle that can help prevent drivers from falling asleep and causing an accident. Start by constructing this model:
|
||||
|
||||
[![EV3 robot with color sensor](/static/coding/line-detection/ev3-robot-color-sensor-down.jpg)](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-color-sensor-down-driving-base-d30ed30610c3d6647d56e17bc64cf6e2.pdf)
|
||||
|
||||
Build red and green “lights” for your robot to detect. You can use LEGO bricks, colored tape, or marker on white paper. Building instructions:
|
||||
|
||||
[![IMAGE: Color Squares](/static/coding/line-detection/ev3-color-squares.jpg)](https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/color%20squares-0a88dfd98bb2e64b5b8151fc422bae36.pdf)
|
||||
|
||||
### ~hint
|
||||
|
||||
If clicking the above images doesn't open the instructions, right-click on the image and choose "Save link as..." to download the PDF.
|
||||
|
||||
### ~
|
||||
|
||||
### Check
|
||||
|
||||
Before you program, check:
|
||||
|
||||
* Are all the wires correctly connected from the motors to ports B and C?
|
||||
* Are the wheels correctly installed?
|
||||
* Are the wheels rotating freely?
|
||||
* Are the wires connected from the Color Sensor to port 3?
|
||||
|
||||
![EV3 Driving Base](/static/coding/line-detection/ev3-robot-driving-base.jpg)
|
||||
|
||||
### Program
|
||||
|
||||
Autonomous cars need to recognize and respond to traffic lights automatically. Create a program that will make your robot stop at red lights. Make sure your robot is only responding to the color red. Once you have succeeded, program your robot to drive forward again when the light changes from red to green.
|
||||
|
||||
Before you program, think about:
|
||||
|
||||
* How will you program the robot to detect a color?
|
||||
* How will you program the robot to stop at a color?
|
||||
* Which programming blocks will you use?
|
||||
|
||||
### ~ hint
|
||||
|
||||
Consider using these blocks in your solution:
|
||||
|
||||
```block
|
||||
loops.forever(function () {
|
||||
|
||||
})
|
||||
motors.largeBC.steer(0, 50)
|
||||
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Red)
|
||||
motors.stopAll()
|
||||
```
|
||||
|
||||
### ~
|
||||
|
||||
### Sample Solution - Red light detection
|
||||
|
||||
1. Loop forever.
|
||||
2. Start motors ``B`` and ``C`` (drive forward).
|
||||
3. Wait for the color sensor to detect the color red.
|
||||
4. Stop all motors.
|
||||
|
||||
```blocks
|
||||
loops.forever(function () {
|
||||
motors.largeBC.steer(0, 50)
|
||||
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Red)
|
||||
motors.stopAll()
|
||||
})
|
||||
```
|
||||
|
||||
### Download and test
|
||||
|
||||
Click **Download** and follow the instructions to get your code onto your EV3 Brick.
|
||||
|
||||
Congratulations! Your robot can stop at a red light.
|
||||
|
||||
Now add to your program and have your robot to drive forward again when the light changes from red to green.
|
||||
|
||||
### Sample Solution - Red and green light detection in a loop
|
||||
|
||||
1. Start motors ``B`` and ``C`` (drive forward).
|
||||
2. Wait for the color sensor to detect the color red.
|
||||
3. Stop all motors.
|
||||
4. Wait for the color sensor to detect the color green.
|
||||
5. Loop forever.
|
||||
|
||||
```blocks
|
||||
loops.forever(function () {
|
||||
motors.largeBC.steer(0, 50)
|
||||
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Red)
|
||||
motors.stopAll()
|
||||
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Green)
|
||||
})
|
||||
```
|
||||
|
||||
### Download and test
|
||||
|
||||
Click **Download** and follow the instructions to get your code onto your EV3 Brick.
|
||||
|
||||
## Contemplate
|
||||
|
||||
To simulate what could happen if a driver falls asleep while driving, your robot could sound an alarm signal when it crosses the line. This feature is often available in new cars.
|
||||
|
||||
Program your robot to perform this function.
|
||||
|
||||
Draw a dark line with tape or marker for your robot to cross.
|
||||
|
||||
### ~hint
|
||||
|
||||
Consider using these blocks in your solution:
|
||||
|
||||
```block
|
||||
motors.largeBC.steer(0, 50)
|
||||
music.playSoundEffect(sounds.systemGeneralAlert)
|
||||
```
|
||||
### ~
|
||||
|
||||
### Sample Solution - Line detection in a loop
|
||||
|
||||
1. Start motors ``B`` and ``C`` (drive forward with a curve toward the line).
|
||||
2. Wait for the color sensor to detect the color black.
|
||||
3. Play sound effect ``system general alert``.
|
||||
4. Start motors ``B`` and ``C`` (drive forward with a curve away from the line).
|
||||
5. Wait for the color sensor to detect the color white.
|
||||
6. Loop forever.
|
||||
|
||||
```blocks
|
||||
loops.forever(function () {
|
||||
motors.largeBC.steer(-30, 20)
|
||||
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Black)
|
||||
music.playSoundEffect(sounds.systemGeneralAlert)
|
||||
motors.largeBC.steer(30, 20)
|
||||
sensors.color3.pauseUntilColorDetected(ColorSensorColor.White)
|
||||
})
|
||||
```
|
||||
|
||||
#### Download and test
|
||||
|
||||
Click **Download** and follow the instructions to get your code onto your EV3 Brick.
|
||||
|
||||
#### Differentiation
|
||||
|
||||
Program your robot to drive on “autopilot” along a given route. You will need to create a program that recognizes and responds to a dark line (or white line). You will create a line-following program and your robot will need to travel along the line without losing contact with it.
|
||||
|
||||
You will need to constantly debug your program in order to make your robot travel as smoothly as possible along the line.
|
||||
|
||||
### ~hint
|
||||
|
||||
Consider using these blocks in your solution:
|
||||
|
||||
```block
|
||||
while (true) {
|
||||
|
||||
}
|
||||
motors.largeBC.steer(0, 50)
|
||||
```
|
||||
|
||||
> **- OR -**
|
||||
|
||||
```block
|
||||
if (true) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### ~
|
||||
|
||||
### Sample Solutions - Line Following in Loop
|
||||
|
||||
#### Method 1
|
||||
|
||||
1. While the Color Sensor detects the color black, start motors ``B`` and ``C`` (drive forward with a curve toward the line).
|
||||
2. While the Color Sensor detects the color white, start motors ``B`` and ``C`` (drive forward with a curve away from the line).
|
||||
3. Loop forever.
|
||||
|
||||
```blocks
|
||||
forever(function () {
|
||||
while (sensors.color3.color() == ColorSensorColor.Black) {
|
||||
motors.largeBC.steer(-30, 50)
|
||||
}
|
||||
while (sensors.color3.color() == ColorSensorColor.White) {
|
||||
motors.largeBC.steer(30, 50)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### Method 2
|
||||
|
||||
1. If the Color Sensor detects the color black, start motors ``B`` and ``C`` (drive forward with a curve toward the line).
|
||||
Else the Color Sensor detects the color white, start motors ``B`` and ``C`` (drive forward with a curve away from the line).
|
||||
2. Loop forever.
|
||||
|
||||
```blocks
|
||||
forever(function () {
|
||||
if (sensors.color3.color() == ColorSensorColor.Black) {
|
||||
motors.largeBC.steer(-30, 50)
|
||||
} else {
|
||||
motors.largeBC.steer(30, 50)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Download and test
|
||||
|
||||
Click **Download** and follow the instructions to get your code onto your EV3 Brick.
|
||||
|
||||
### Share
|
||||
|
||||
Think about:
|
||||
|
||||
* What challenged you?
|
||||
* Were there any surprises?
|
||||
* How can you improve your program?
|
||||
* Can your program be more streamlined? Have you used too many blocks?
|
||||
* Is there a more efficient way to build your program?
|
||||
* How can your program be used in real-world scenarios?
|
||||
|
||||
Personalize:
|
||||
|
||||
* Click on the **JavaScript** tab and experiment with changing the values in the code.
|
||||
* Add a custom image or sounds from the ``||brick:Brick||`` or ``||music:Music||`` menus.
|
||||
* Create a video of your project, especially your final presentation and your robot’s performance. Explain some important features of your software program.
|
||||
* Include an image of your program with comments.
|
||||
* Add a team photograph!
|
||||
|
||||
Congratulations! What will you design next?
|
@ -1,143 +0,0 @@
|
||||
# Object Detection
|
||||
|
||||
Design ways to avoid accidents between vehicles and objects in the road.
|
||||
|
||||
![Deer in the road](/static/coding/object-detection/road-deer.jpg)
|
||||
|
||||
## Connect
|
||||
|
||||
Think about:
|
||||
|
||||
* In what driving situations can a car hit an obstacle?
|
||||
* What do you need to be aware of to avoid collisions with obstacles?
|
||||
* What causes traffic jams in high density areas?
|
||||
|
||||
## Construct
|
||||
|
||||
### Build
|
||||
|
||||
Build a @boardname@ vehicle that can avoid accidents between vehicles and objects in the road. Start by constructing this model:
|
||||
|
||||
[![EV3 Robot Driving Base](/static/coding/object-detection/ev3-robot-driving-base.jpg)](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-ultrasonic-sensor-driving-base-61ffdfa461aee2470b8ddbeab16e2070.pdf)
|
||||
|
||||
Build an obstacle for your robot to detect. You can build the **cuboid model** out of LEGO bricks or an obstacle of your choice.
|
||||
|
||||
[![Cubiod block](/static/coding/object-detection/ev3-cuboid.jpg)](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-cuboid-dc93b2e60bed2981e76b3bac9ea04558.pdf)
|
||||
|
||||
### ~hint
|
||||
|
||||
If clicking the above images doesn't open the instructions, right-click on the image and choose "Save link as..." to download the PDF.
|
||||
|
||||
### ~
|
||||
|
||||
### Check
|
||||
|
||||
Before you program, check:
|
||||
|
||||
* Are all the wires correctly connected from the motors to ports B and C?
|
||||
* Are the wheels correctly installed?
|
||||
* Are the wheels rotating freely?
|
||||
* Are the wires connected from the Ultrasonic Sensor to port 4?
|
||||
|
||||
### Program
|
||||
|
||||
* Program your robot to detect any obstacles that might appear while the robot is moving forward (or backward).
|
||||
* Make the robot stop when it detects an object that is less than 20 cm away.
|
||||
|
||||
Before you program, think about:
|
||||
* How will you program the robot to detect obstacles?
|
||||
* How will you program the robot to stop at obstacles?
|
||||
* Which programming blocks will you use?
|
||||
|
||||
### ~hint
|
||||
|
||||
Consider using these blocks in your solution:
|
||||
|
||||
```block
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
|
||||
})
|
||||
motors.largeBC.steer(0, 50)
|
||||
pauseUntil(() => true)
|
||||
let near = sensors.ultrasonic4.distance() < 20
|
||||
motors.stopAll()
|
||||
```
|
||||
|
||||
### ~
|
||||
|
||||
### Sample Solution
|
||||
|
||||
1. Start the program when EV3 ``enter`` button is pressed.
|
||||
2. Turn motors ``B`` and ``C`` on at speed ``50``.
|
||||
3. Wait until Ultrasonic Sensor detects an obstacle at a distance of less than ``20`` cm.
|
||||
4. Stops all motors.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
motors.largeBC.steer(0, 50)
|
||||
pauseUntil(() => sensors.ultrasonic4.distance() < 20)
|
||||
motors.stopAll()
|
||||
})
|
||||
```
|
||||
|
||||
### Download and test
|
||||
|
||||
Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the ``center`` button on the EV3 Brick to run the program.
|
||||
|
||||
## Contemplate
|
||||
|
||||
On the road, when a driver sees and object, they slow their car down before coming to a full stop.
|
||||
|
||||
Program your EV3 Driving Base to do the same.
|
||||
|
||||
If the Ultrasonic Sensor:
|
||||
|
||||
* Detects an object less than `10` cm away, make the robot stop.
|
||||
* Detects an object between `10` and `20` cm away, make the robot slow down.
|
||||
* Does not detect any object, continue to move at full speed.
|
||||
|
||||
### ~hint
|
||||
|
||||
Consider using this block in your solution:
|
||||
|
||||
```block
|
||||
if (true) {
|
||||
}
|
||||
```
|
||||
|
||||
### ~
|
||||
|
||||
### Sample Solution
|
||||
|
||||
```blocks
|
||||
loops.forever(function () {
|
||||
motors.largeBC.steer(0, 50)
|
||||
if (sensors.ultrasonic4.distance() < 10) {
|
||||
motors.stopAll()
|
||||
} else if (sensors.ultrasonic4.distance() < 20) {
|
||||
motors.largeBC.steer(0, 10)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Download and test
|
||||
|
||||
Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the ``center`` button on the EV3 Brick to run the program.
|
||||
|
||||
## Continue
|
||||
|
||||
* Get together with other building teams and make a traffic jam by placing all of your robots in a line with varying amounts of space between them.
|
||||
* Have everyone start their robots at the same time and see what happens.
|
||||
* Refine your programs so that all of the robots continue driving at the same speed with equal distances between them.
|
||||
* Click on the JavaScript tab and experiment with changing the values in the code.
|
||||
* Add a custom image or sounds from the Brick or Music menus.
|
||||
|
||||
### Share
|
||||
|
||||
* Share what you think “efficiency in programming” means.
|
||||
* Explore the different solutions other programmers came up with.
|
||||
* Create a video of your project, especially your final presentation and your robot’s performance. Explain some important features of your software program.
|
||||
* Include an image of your program with comments.
|
||||
* Add a team photograph!
|
||||
|
||||
Congratulations! What will you design next?
|
@ -1,11 +0,0 @@
|
||||
# Reverse Beeper Activity 1
|
||||
|
||||
```blocks
|
||||
forever(function () {
|
||||
music.playTone(440, sensors.ultrasonic4.distance());
|
||||
pause(50)
|
||||
})
|
||||
motors.largeBC.run(-20);
|
||||
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear);
|
||||
motors.largeBC.stop();
|
||||
```
|
@ -1,13 +0,0 @@
|
||||
# Reverse Beeper Activity 2
|
||||
|
||||
```blocks
|
||||
forever(function () {
|
||||
if (motors.largeB.speed() != 0 && sensors.ultrasonic4.distance() < 20) {
|
||||
music.playTone(440, sensors.ultrasonic4.distance());
|
||||
pause(50)
|
||||
}
|
||||
})
|
||||
motors.largeBC.run(-20);
|
||||
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear);
|
||||
motors.largeBC.stop();
|
||||
```
|
@ -1,20 +0,0 @@
|
||||
# Reverse Beeper Activity 2
|
||||
|
||||
```blocks
|
||||
let beep = false
|
||||
beep = true
|
||||
control.runInParallel(function () {
|
||||
motors.largeBC.run(-20)
|
||||
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear)
|
||||
motors.largeBC.stop()
|
||||
beep = false
|
||||
})
|
||||
control.runInParallel(function () {
|
||||
while (beep) {
|
||||
if (sensors.ultrasonic4.distance() < 20) {
|
||||
music.playTone(440, sensors.ultrasonic4.distance())
|
||||
pause(50)
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
@ -1,14 +0,0 @@
|
||||
# Reversing the robot Activity 1
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Bumped, function () {
|
||||
motors.largeBC.run(50)
|
||||
sensors.touch1.pauseUntil(ButtonEvent.Pressed)
|
||||
motors.largeBC.run(0)
|
||||
pause(1000)
|
||||
brick.setStatusLight(StatusLight.OrangeFlash)
|
||||
motors.largeBC.run(-50)
|
||||
pause(2000)
|
||||
motors.largeBC.run(0)
|
||||
})
|
||||
```
|
@ -1,15 +0,0 @@
|
||||
# Reversing the robot Activity 2
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Bumped, function () {
|
||||
sensors.touch1.pauseUntil(ButtonEvent.Pressed)
|
||||
motors.largeBC.run(50)
|
||||
sensors.touch2.pauseUntil(ButtonEvent.Pressed)
|
||||
motors.largeBC.run(0)
|
||||
pause(1000)
|
||||
brick.setStatusLight(StatusLight.OrangeFlash)
|
||||
motors.largeBC.run(-50)
|
||||
pause(2000)
|
||||
motors.largeBC.run(0)
|
||||
})
|
||||
```
|
@ -1,19 +0,0 @@
|
||||
# Reversing the robot Activity 3
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Bumped, function () {
|
||||
brick.showImage(images.eyesSleeping)
|
||||
sensors.touch1.pauseUntil(ButtonEvent.Pressed)
|
||||
brick.showImage(images.eyesNeutral)
|
||||
motors.largeBC.run(50)
|
||||
sensors.touch2.pauseUntil(ButtonEvent.Pressed)
|
||||
brick.showImage(images.eyesTiredMiddle)
|
||||
motors.largeBC.run(0)
|
||||
pause(1000)
|
||||
brick.setStatusLight(StatusLight.OrangeFlash)
|
||||
brick.showImage(images.eyesDizzy)
|
||||
motors.largeBC.run(-50)
|
||||
pause(2000)
|
||||
motors.largeBC.run(0)
|
||||
})
|
||||
```
|
@ -1,32 +0,0 @@
|
||||
# Roaming Activity 1
|
||||
|
||||
```blocks
|
||||
let drive: number[] = []
|
||||
brick.buttonLeft.onEvent(ButtonEvent.Bumped, function () {
|
||||
drive.push(1)
|
||||
})
|
||||
brick.buttonRight.onEvent(ButtonEvent.Bumped, function () {
|
||||
drive.push(3)
|
||||
})
|
||||
brick.buttonUp.onEvent(ButtonEvent.Bumped, function () {
|
||||
drive.push(4)
|
||||
})
|
||||
brick.buttonDown.onEvent(ButtonEvent.Bumped, function () {
|
||||
drive.push(5)
|
||||
})
|
||||
pauseUntil(() => drive.length >= 5)
|
||||
pause(1000)
|
||||
music.playSoundEffectUntilDone(sounds.communicationGo)
|
||||
for (let d of drive) {
|
||||
if (d == 1) {
|
||||
motors.largeC.run(50, 360, MoveUnit.Degrees)
|
||||
} else if (d == 3) {
|
||||
motors.largeB.run(50, 360, MoveUnit.Degrees)
|
||||
} else if (d == 4) {
|
||||
motors.largeBC.run(50, 360, MoveUnit.Degrees)
|
||||
} else {
|
||||
motors.largeBC.run(-50, 360, MoveUnit.Degrees)
|
||||
}
|
||||
}
|
||||
music.playSoundEffectUntilDone(sounds.communicationGameOver)
|
||||
```
|
@ -1,36 +0,0 @@
|
||||
# Roaming Activity 2
|
||||
|
||||
```blocks
|
||||
let drive: number[] = []
|
||||
brick.buttonLeft.onEvent(ButtonEvent.Bumped, function () {
|
||||
drive.push(1)
|
||||
music.playSoundEffectUntilDone(sounds.systemClick)
|
||||
})
|
||||
brick.buttonRight.onEvent(ButtonEvent.Bumped, function () {
|
||||
drive.push(3)
|
||||
music.playSoundEffectUntilDone(sounds.systemClick)
|
||||
})
|
||||
brick.buttonUp.onEvent(ButtonEvent.Bumped, function () {
|
||||
drive.push(4)
|
||||
music.playSoundEffectUntilDone(sounds.systemClick)
|
||||
})
|
||||
brick.buttonDown.onEvent(ButtonEvent.Bumped, function () {
|
||||
drive.push(5)
|
||||
music.playSoundEffectUntilDone(sounds.systemClick)
|
||||
})
|
||||
brick.buttonEnter.pauseUntil(ButtonEvent.Bumped);
|
||||
pause(1000)
|
||||
music.playSoundEffectUntilDone(sounds.communicationGo)
|
||||
for (let d of drive) {
|
||||
if (d == 1) {
|
||||
motors.largeC.run(50, 360, MoveUnit.Degrees)
|
||||
} else if (d == 3) {
|
||||
motors.largeB.run(50, 360, MoveUnit.Degrees)
|
||||
} else if (d == 4) {
|
||||
motors.largeBC.run(50, 360, MoveUnit.Degrees)
|
||||
} else {
|
||||
motors.largeBC.run(-50, 360, MoveUnit.Degrees)
|
||||
}
|
||||
}
|
||||
music.playSoundEffectUntilDone(sounds.communicationGameOver)
|
||||
```
|
@ -1,12 +0,0 @@
|
||||
# Three Point Turn Activity 1
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Bumped, function () {
|
||||
motors.largeBC.tank(75, 30)
|
||||
pause(1500)
|
||||
motors.largeBC.tank(-30, -75)
|
||||
pause(1000)
|
||||
motors.largeBC.tank(50, 50)
|
||||
pause(3000)
|
||||
})
|
||||
```
|
@ -1,14 +0,0 @@
|
||||
# Three Point Turn Activity 2
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Bumped, function () {
|
||||
motors.largeBC.tank(75, 30)
|
||||
pause(1500)
|
||||
motors.largeBC.tank(-30, -75)
|
||||
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear);
|
||||
motors.largeBC.tank(0, 0)
|
||||
pause(1000)
|
||||
motors.largeBC.tank(50, 50)
|
||||
pause(3000)
|
||||
})
|
||||
```
|
@ -1,15 +0,0 @@
|
||||
# Three Point Turn Activity 3
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Bumped, function () {
|
||||
motors.largeBC.tank(75, 30)
|
||||
pause(1500)
|
||||
motors.largeBC.tank(-30, -75)
|
||||
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear);
|
||||
motors.largeBC.tank(0, 0)
|
||||
music.playSoundEffect(sounds.animalsDogBark1)
|
||||
pause(1000)
|
||||
motors.largeBC.tank(50, 50)
|
||||
pause(3000)
|
||||
})
|
||||
```
|
@ -1,9 +0,0 @@
|
||||
# Traffic Lights Activity 1
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Bumped, function () {
|
||||
motors.largeBC.tank(20, 20)
|
||||
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Red)
|
||||
motors.largeBC.tank(0, 0)
|
||||
})
|
||||
```
|
@ -1,10 +0,0 @@
|
||||
# Traffic Lights Activity 2
|
||||
|
||||
```blocks
|
||||
sensors.color3.onColorDetected(ColorSensorColor.Red, function () {
|
||||
motors.largeBC.tank(0, 0)
|
||||
})
|
||||
sensors.color3.onColorDetected(ColorSensorColor.Green, function () {
|
||||
motors.largeBC.tank(20, 20)
|
||||
})
|
||||
```
|
@ -1,11 +0,0 @@
|
||||
# Traffic Lights Activity 3
|
||||
|
||||
```blocks
|
||||
forever(function () {
|
||||
if (sensors.color3.light(LightIntensityMode.Reflected) < 15) {
|
||||
motors.largeBC.tank(30, 12)
|
||||
} else {
|
||||
motors.largeBC.tank(12, 30)
|
||||
}
|
||||
})
|
||||
```
|
@ -1,29 +0,0 @@
|
||||
# Design Engineering Projects
|
||||
|
||||
## Projects
|
||||
|
||||
```codecard
|
||||
[
|
||||
{
|
||||
"name": "Make It Move Without Wheels",
|
||||
"description": "Design, build and program a robot that can move itself using no wheels for locomotion.",
|
||||
"imageUrl": "/static/lessons/make-it-move-without-wheels.png",
|
||||
"url": "/design-engineering/make-it-move",
|
||||
"cardType": "side"
|
||||
},
|
||||
{
|
||||
"name": "Make It Smarter and Faster",
|
||||
"description": "Design, build and program a robotic creature that can sense its environment and respond by moving.",
|
||||
"imageUrl": "/static/lessons/make-it-smarter-and-faster.png",
|
||||
"url": "/design-engineering/make-it-smarter",
|
||||
"cardType": "side"
|
||||
},
|
||||
{
|
||||
"name": "Make a System that Communicates",
|
||||
"description": "Design, build and program a robotic system that follows a path and communicates its position at least twice along the way.",
|
||||
"imageUrl": "/static/lessons/make-a-system-that-communicates.png",
|
||||
"url": "/design-engineering/make-it-communicate",
|
||||
"cardType": "side"
|
||||
}
|
||||
]
|
||||
```
|
@ -1,163 +0,0 @@
|
||||
# Make A System That Communicates
|
||||
|
||||
## Connect
|
||||
|
||||
### Design Brief
|
||||
|
||||
Design, build and program a robotic system that follows a path and communicates its position at least twice along the way.
|
||||
|
||||
https://www.youtube.com/watch?v=6piMI1JPDQc
|
||||
|
||||
* Robotic systems are built from smaller, related subsystems. Look at the automobile system shown in the video. What subsystems can you see?
|
||||
* What kinds of robots follow a path?
|
||||
* What kind of system do you want to make?
|
||||
|
||||
### Brainstorm
|
||||
|
||||
Discuss different solutions to the design brief.
|
||||
|
||||
Think about:
|
||||
* What kind of motorized mechanism can be used to control the movements of a robot?
|
||||
* How can the robot sense where it is along the path?
|
||||
* How can the robot communicate its position?
|
||||
|
||||
![EV3 + LEGO Bricks](/static/lessons/make-it-communicate/ev3-plus-parts.jpg)
|
||||
|
||||
## Construct
|
||||
|
||||
### Build
|
||||
|
||||
You can start by tinkering with the LEGO elements in the picture and then build on.
|
||||
|
||||
More building ideas:
|
||||
|
||||
[![EV3 Frames](/static/lessons/make-it-communicate/ev3-frames.jpg)](https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/ev3%20frames-5054ee378e624fb4cb31158d2fc8e5cf.pdf)
|
||||
|
||||
[![Tracks](/static/lessons/make-it-communicate/ev3-tracks.jpg)](https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/tracks-32d7554813af3f25cf5012d54a4bad2b.pdf)
|
||||
|
||||
[![Color Sensor 2](/static/lessons/make-it-communicate/ev3-color-sensor2.jpg)](https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/color%20sensor_v2-e7fd54b6fa3cdfe36f414c1d2510f9cb.pdf)
|
||||
|
||||
### ~hint
|
||||
|
||||
If clicking the above images doesn't open the instructions, right-click on the image and choose "Save link as..." to download the PDF.
|
||||
|
||||
### ~
|
||||
|
||||
|
||||
Build a path for your robot to follow. You can use electrical tape on a floor, or marker on paper. You can use objects as milestones to indicate a path that can be detected by either the Touch Sensor, Color Sensor, or Ultrasonic Sensor.
|
||||
|
||||
### Program
|
||||
|
||||
Before you program, think about:
|
||||
|
||||
* How will you program the robot to follow a path?
|
||||
* How will you program the robot to communicate its position?
|
||||
* Which programming blocks will you use?
|
||||
|
||||
### ~hint
|
||||
|
||||
Explore the different Motor and Sensor blocks in the programming menu.
|
||||
|
||||
### ~
|
||||
|
||||
### Sample Solution
|
||||
|
||||
[![Video: EV3 Track Rover](/static/lessons/make-it-communicate/ev3-track-rover.jpg)](https://legoeducation.23video.com/v.ihtml/player.html?token=79c99735f906403a4dd7f2909935983d&source=embed&photo%5fid=19857954)
|
||||
|
||||
The Track Rover follows a path using the color sensor. It identifies two locations by color.
|
||||
|
||||
Track Rover solution combines these building ideas:
|
||||
|
||||
* EV3 frames
|
||||
* Tracks
|
||||
* Color sensor 2
|
||||
|
||||
Two copies of the tracks are built: one for the right side and a mirror image for the left side.
|
||||
|
||||
[![Track rover assembled](/static/lessons/make-it-communicate/ev3-track-rover2.jpg)](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/ev3-dep/building%20instructions/track-rover-bi-6aadb1b053df0c58a0dea108b5ce0eea.pdf)
|
||||
|
||||
### ~hint
|
||||
|
||||
If clicking the above image doesn't open the instructions, right-click on the image and choose "Save link as..." to download the PDF.
|
||||
|
||||
### ~
|
||||
|
||||
### Sample Program Solution
|
||||
|
||||
This program works with the Track Rover. If you create a different robot, adjust the program to fit your solution.
|
||||
|
||||
Program summary:
|
||||
|
||||
* If the Color Sensor sees black, Motor B runs at -50 power and Motor C turns off.
|
||||
* If the Color Sensor sees white, Motor B turns off and Motor C runs at -50 power.
|
||||
* If the Color Sensor sees green, all motors stop and the green sound plays.
|
||||
* The robot waits one second, then motors move forward.
|
||||
* If the Color Sensor sees red, all motors stop, and the red sound plays.
|
||||
* The robot waits one second, then motors move forward.
|
||||
* Loops unlimited.
|
||||
|
||||
```blocks
|
||||
forever(function () {
|
||||
if (sensors.color3.color() == ColorSensorColor.Black) {
|
||||
motors.largeB.run(-50)
|
||||
motors.largeC.run(0)
|
||||
} else if (sensors.color3.color() == ColorSensorColor.White) {
|
||||
motors.largeC.run(-50)
|
||||
motors.largeB.run(0)
|
||||
} else if (sensors.color3.color() == ColorSensorColor.Green) {
|
||||
motors.stopAll()
|
||||
music.playSoundEffectUntilDone(sounds.colorsGreen)
|
||||
motors.largeBC.run(-50)
|
||||
} else if (sensors.color3.color() == ColorSensorColor.Red) {
|
||||
motors.stopAll()
|
||||
music.playSoundEffectUntilDone(sounds.colorsRed)
|
||||
motors.largeBC.run(-50)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Download and test
|
||||
|
||||
Click Download and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
## Contemplate
|
||||
|
||||
### Test and Analyze
|
||||
|
||||
As you work on your solution:
|
||||
|
||||
1. Describe one part of your design that worked especially well.
|
||||
2. Describe one design change that you had to make.
|
||||
3. What will you try next?
|
||||
|
||||
|
||||
### Review and Revise
|
||||
|
||||
Take a moment to reflect on your robot solution.
|
||||
|
||||
Think about:
|
||||
|
||||
* Can the robot’s movement be more accurate?
|
||||
* What are some ways that others have solved the problem?
|
||||
|
||||
Describe two ways you could improve your robot.
|
||||
|
||||
## Continue
|
||||
|
||||
### Personalize your project
|
||||
|
||||
* Add/remove LEGO elements to improve the way your robot moves.
|
||||
* Click on the JavaScript tab and experiment with changing the values in the code.
|
||||
* Add a custom image or sounds by adding blocks from the Brick or Music menus.
|
||||
|
||||
## Communicate
|
||||
|
||||
Here are some ideas:
|
||||
|
||||
* Create a video of your project, especially your final presentation and your robot’s performance.
|
||||
* Explain some important features of your software program.
|
||||
* Produce a building guide for your model by taking a series of photographs as you deconstruct it.
|
||||
* Include an image of your program with comments.
|
||||
* Add a team photograph!
|
||||
|
||||
Congratulations! What will you design next?
|
@ -1,105 +0,0 @@
|
||||
# Make It Move Without Wheels
|
||||
|
||||
## Connect
|
||||
|
||||
### Design Brief
|
||||
|
||||
Design, build and program a robot that can move itself using no wheels for locomotion.
|
||||
|
||||
![Make it move banner](/static/lessons/make-it-move/make-it-move-without-wheels.png)
|
||||
|
||||
Your robot will:
|
||||
|
||||
* Go a distance of at least 30cm
|
||||
* Use at least one motor
|
||||
* Use NO wheels for locomotion
|
||||
|
||||
### Brainstorm
|
||||
|
||||
In nature, creatures use many methods to get around. None of them, however, use wheels to move. Can we copy the method of animal locomotion with our robot? Using motors and legs, make a robot that can move without using any wheels.
|
||||
|
||||
## Construct
|
||||
|
||||
### Build
|
||||
|
||||
Think about a creature’s movement for inspiration. Will you make the robot walk, crawl, hop, or wiggle? Your mechanism can be attached or unattached to the EV3 Brick. You can start by tinkering with the LEGO elements in the picture above and then build on.
|
||||
|
||||
### Building Hint
|
||||
|
||||
If you want some building help you can follow these instructions.
|
||||
|
||||
[![Toddle Bot](/static/lessons/make-it-move/toddle-bot.jpg)](https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/toddle%20bot-3dcad146d7f5deac4753f93e9dcc0739.pdf)
|
||||
|
||||
Click [here](https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/toddle%20bot-3dcad146d7f5deac4753f93e9dcc0739.pdf)
|
||||
|
||||
### ~hint
|
||||
|
||||
If clicking the above image or link doesn't open the instructions, right-click on the link and choose "Save link as..." to download the PDF.
|
||||
|
||||
### ~
|
||||
|
||||
### Program
|
||||
|
||||
Before you program, think about:
|
||||
|
||||
* How will you program the robot to move?
|
||||
* How will you program the robot to stop?
|
||||
* How will you program the robot to display the distance moved?
|
||||
|
||||
Which programming blocks will you use:
|
||||
|
||||
* To turn on and turn off the motor or motors?
|
||||
* To display the distance moved?
|
||||
|
||||
### Sample Code
|
||||
|
||||
Example code of a robot that moves without wheels using one motor:
|
||||
|
||||
* The robot moves with ``large motor D`` rotating at ``-100`` speed
|
||||
* The robot moves for ``30000`` milliseconds (30 seconds)
|
||||
* The robot stops
|
||||
* The robot displays the text ``"30cm"``
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
motors.largeD.run(-100)
|
||||
loops.pause(30000)
|
||||
motors.stopAll()
|
||||
brick.showString("30cm", 1)
|
||||
})
|
||||
```
|
||||
|
||||
### Download and test
|
||||
|
||||
Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
## Contemplate
|
||||
|
||||
### Test and Analyze
|
||||
|
||||
Think about:
|
||||
|
||||
* Is the robot using something other than wheels to move? Trace the movement from the motor axle to the mechanism(s) that drives the robot forward, backward or sideways. Wheels can be used to stabilize the robot but not to drive it.
|
||||
* Does the robot display the distance moved? Is it accurate? How do you know?
|
||||
* What is one part of your design that worked well?
|
||||
* What is a change that you need to make?
|
||||
* What will you try next?
|
||||
|
||||
## Continue
|
||||
|
||||
### Personalize your project
|
||||
|
||||
* Add/remove LEGO elements to improve the way your robot moves. Will your robot walk, wiggle, hop, or slither? Will it move slower, faster or farther?
|
||||
* Click on the JavaScript tab and experiment with changing the values in the code.
|
||||
* Add a custom image or sounds by adding blocks from the Brick or Music menus.
|
||||
* Does your robot resemble a creature? Add arts and crafts materials to your project.
|
||||
|
||||
## Communicate
|
||||
|
||||
* Create a video of your project, especially your final presentation and your robot’s performance.
|
||||
* Explain some important features of your software program.
|
||||
* Produce a building guide for your model by taking a series of photographs as you deconstruct it.
|
||||
* Include an image of your program with comments.
|
||||
* Add a team photograph!
|
||||
|
||||
Congratulations! What will you design next?
|
@ -1,178 +0,0 @@
|
||||
# Make It Smarter and Faster
|
||||
|
||||
## Connect
|
||||
|
||||
### Design Brief
|
||||
|
||||
Design, build and program a robotic creature that can sense its environment and respond by moving.
|
||||
|
||||
https://www.youtube.com/watch?v=y9-A_C_08KY
|
||||
|
||||
* What do the robots in the video need to be able to sense, plan, and act?
|
||||
* What senses do humans have and why are they important to us?
|
||||
* How many human-like senses do you see the robots demonstrating?
|
||||
|
||||
### Brainstorm
|
||||
|
||||
Discuss different solutions to the design brief.
|
||||
|
||||
Think about:
|
||||
|
||||
* What kind of creature can it be?
|
||||
* How can it move?
|
||||
* What does it need to be aware so that it stays safe, well fed and warm (or cool)?
|
||||
* Is it looking for food, a safe place to hide or a warm place to soak up the sun?
|
||||
* Will the creature need to move fast or slow?
|
||||
* Will it need to turn?
|
||||
* Will it need to go backward?
|
||||
|
||||
![EV3 and bricks](/static/lessons/make-it-smarter/bricks.png)
|
||||
|
||||
## Construct
|
||||
|
||||
### Build
|
||||
|
||||
Think about a creature’s movement for inspiration. Your mechanism can be attached or unattached to the EV3 Brick. You can start by tinkering with the LEGO elements in the picture add then build on.
|
||||
|
||||
More building ideas:
|
||||
|
||||
|
||||
* [EV3 Frames]
|
||||
* [Color Sensor 1]
|
||||
* [Gyro Sensor]
|
||||
* [Ultrasonic Sensor]
|
||||
* [Touch Sensor]
|
||||
* [Jaw]
|
||||
* [Leg 1]
|
||||
* [Leg 2]
|
||||
* [Leg 3]
|
||||
|
||||
### ~hint
|
||||
|
||||
If clicking the above links doesn't open the instructions, right-click on the image and choose "Save link as..." to download the PDF.
|
||||
|
||||
### ~
|
||||
|
||||
### Program
|
||||
|
||||
Before you program, think about:
|
||||
|
||||
* How will you program the robot to sense?
|
||||
* How will you program the robot to respond?
|
||||
* Which programming blocks will you use?
|
||||
|
||||
### ~hint
|
||||
|
||||
**Hint:** Explore the different Sensor blocks in the Sensors Menu
|
||||
|
||||
### ~
|
||||
|
||||
### Sample Solution
|
||||
|
||||
The Insect uses its Ultrasonic Sensor to sense danger and move away from a threat.
|
||||
|
||||
https://www.youtube.com/watch?v=PoeYoiXHHE4
|
||||
<br/>
|
||||
The Insect solution combines these building ideas:
|
||||
|
||||
* [EV3 Frames]
|
||||
* [Leg 2]
|
||||
* [Leg 3]
|
||||
* [Ultrasonic Sensor]
|
||||
|
||||
Four copies of Leg 3 are built: one for the front left, one for the back right, and two mirror copies for the front right and back left.
|
||||
|
||||
Building Instructions:
|
||||
|
||||
[![Insect robot](/static/lessons/make-it-smarter/insect-bot.jpg)](https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/insect-94b8a46f0dc5082c9d78ddb734626dc9.pdf)
|
||||
|
||||
### ~hint
|
||||
|
||||
If clicking the above images or links doesn't open the instructions, right-click on the link and choose "Save link as..." to download the PDF.
|
||||
|
||||
### ~
|
||||
|
||||
### Sample Solution
|
||||
|
||||
This program checks if the Ultrasonic Sensor senses something near.
|
||||
|
||||
The blocks inside the ``||loops:forever||`` loop have these actions:
|
||||
|
||||
1. Turn on the ``green`` EV3 Brick Status Light.
|
||||
2. Wait for Ultrasonic Sensor to detect an object.
|
||||
3. Turn on Motors ``A`` and ``D`` in opposite directions.
|
||||
4. Wait for one and a half seconds (``1500`` milli seconds).
|
||||
5. Reverse the direction of Motors ``A`` and ``D``.
|
||||
6. Wait for one and a half seconds.
|
||||
7. Stop all motors.
|
||||
8. Make an insect chirping sound.
|
||||
9. Loop continuously so that the insect wanders around when the Ultrasonic Sensor is detects something.
|
||||
|
||||
```blocks
|
||||
forever(function () {
|
||||
brick.setStatusLight(StatusLight.Green)
|
||||
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectDetected)
|
||||
motors.largeAD.tank(50, -50)
|
||||
pause(1500)
|
||||
motors.largeAD.tank(-50, 50)
|
||||
pause(1500)
|
||||
motors.stopAll()
|
||||
music.playSoundEffectUntilDone(sounds.animalsInsectChirp)
|
||||
})
|
||||
```
|
||||
|
||||
### Download and test
|
||||
|
||||
Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
## Contemplate
|
||||
|
||||
### Test and Analyze
|
||||
|
||||
As you work on your solution:
|
||||
1. Describe one part of your design that worked especially well.
|
||||
2. Describe one design change that you had to make.
|
||||
3. What will you try next?
|
||||
|
||||
### Review and Revise
|
||||
|
||||
Take a moment to reflect on your robot solution.
|
||||
|
||||
Think about:
|
||||
|
||||
* Does your robot move when the sensor is activated?
|
||||
* If not, what will you change to make the robot’s ability to sense and respond more obvious?
|
||||
* What other behaviors can you add to the robot to make it more realistic?
|
||||
|
||||
Describe two ways you could improve your robot.
|
||||
|
||||
## Continue
|
||||
|
||||
Personalize your project:
|
||||
|
||||
* Add/remove LEGO elements to improve the way your robot moves.
|
||||
* Click on the JavaScript tab and experiment with changing the values in the code.
|
||||
* Add a custom image or sounds by adding blocks from the Brick or Music menus.
|
||||
* Does your robot resemble a creature? Maybe add more craft materials to your project.
|
||||
|
||||
## Communicate
|
||||
|
||||
Here are some ideas:
|
||||
|
||||
* Create a video of your project, especially your final presentation and your robot’s performance. Explain some important features of your software program.
|
||||
* Produce a building guide for your model by taking a series of photographs as you deconstruct it.
|
||||
* Include an image of your program with comments.
|
||||
* Add a team photograph!
|
||||
|
||||
Congratulations! What will you design next?
|
||||
|
||||
|
||||
[EV3 Frames]: https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/ev3%20frames-5054ee378e624fb4cb31158d2fc8e5cf.pdf
|
||||
[Color Sensor 1]: https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/color%20sensor_v1-16a7231bdc187cd88a8da120c68f58d5.pdf
|
||||
[Gyro Sensor]: https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/gyro%20sensor-6f0fdbd82ae45fe0effa0ebf3f460f3d.pdf
|
||||
[Ultrasonic Sensor]: https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/ultrasonic%20sensor-a56156c72e8946ed4c58c5e69f3520d3.pdf
|
||||
[Touch Sensor]: https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/touch%20sensor-868fda1b9d6070a0a034fb22456a7fc9.pdf
|
||||
[Jaw]: https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/jaw-ee93e8f3243e4d30cd34b0c337c33653.pdf
|
||||
[Leg 1]: https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/leg%201-c14624046ea3a95148820ed404f5ac65.pdf
|
||||
[Leg 2]: https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/leg%202-8855c35b990205f6b9d7130687a3d4db.pdf
|
||||
[Leg 3]: https://le-www-live-s.legocdn.com/sc/media/files/support/mindstorms%20ev3/building-instructions/design%20engineering%20projects/leg%203-575d52ef15fb79f1e4d3350d36607160.pdf
|
222
docs/examples.md
222
docs/examples.md
@ -2,225 +2,7 @@
|
||||
|
||||
Here are some fun programs for your @boardname@!
|
||||
|
||||
## Maker
|
||||
|
||||
```codecard
|
||||
[
|
||||
{
|
||||
"name": "Sound Of Color",
|
||||
"description": "Play different sounds based on the color",
|
||||
"url":"/maker/sound-of-color",
|
||||
"cardType": "example",
|
||||
"imageUrl": "/static/maker/sound-of-color.png"
|
||||
},
|
||||
{
|
||||
"name": "Security Gadget",
|
||||
"description": "Raise the alarm when your brick is lifted!",
|
||||
"url":"/maker/security-gadget",
|
||||
"cardType": "example",
|
||||
"imageUrl": "/static/maker/security-gadget.png"
|
||||
},
|
||||
{
|
||||
"name": "Movement Detector",
|
||||
"description": "Raise the alarm when an movement sneaks in",
|
||||
"url":"/maker/movement-detector",
|
||||
"cardType": "example",
|
||||
"imageUrl": "/static/maker/movement-detector.png"
|
||||
},
|
||||
{
|
||||
"name": "Puppet",
|
||||
"description": "Build an automated puppet",
|
||||
"url":"/maker/puppet",
|
||||
"cardType": "example",
|
||||
"imageUrl": "/static/maker/puppet.png"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Three Point Turn
|
||||
|
||||
```codecard
|
||||
[
|
||||
{
|
||||
"name": "Three Point Turn 1",
|
||||
"description": "Activity 1",
|
||||
"url":"/coding/three-point-turn-1",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Three Point Turn 2",
|
||||
"description": "Activity 2",
|
||||
"url":"/coding/three-point-turn-2",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Three Point Turn 3",
|
||||
"description": "Activity 3",
|
||||
"url":"/coding/three-point-turn-3",
|
||||
"cardType": "example"
|
||||
}]
|
||||
```
|
||||
|
||||
## Reversing the robot
|
||||
|
||||
```codecard
|
||||
[{
|
||||
"name": "Reversing the robot 1",
|
||||
"description": "Activity 1",
|
||||
"url":"/coding/reversing-the-robot-1",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Reversing the robot 2",
|
||||
"description": "Activity 2",
|
||||
"url":"/coding/reversing-the-robot-2",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Reversing the robot 3",
|
||||
"description": "Activity 3",
|
||||
"url":"/coding/reversing-the-robot-3",
|
||||
"cardType": "example"
|
||||
}]
|
||||
```
|
||||
|
||||
## Light the way
|
||||
|
||||
```codecard
|
||||
[{
|
||||
"name": "Light the way 1",
|
||||
"description": "Activity 1",
|
||||
"url":"/coding/light-the-way-1",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Light the way 2",
|
||||
"description": "Activity 2",
|
||||
"url":"/coding/light-the-way-2",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Light the way 3",
|
||||
"description": "Activity 3",
|
||||
"url":"/coding/light-the-way-3",
|
||||
"cardType": "example"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Traffic Lights
|
||||
|
||||
```codecard
|
||||
[{
|
||||
"name": "Traffic Lights 1",
|
||||
"description": "Activity 1",
|
||||
"url":"/coding/traffic-lights-1",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Traffic Lights 2",
|
||||
"description": "Activity 2",
|
||||
"url":"/coding/traffic-lights-2",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Traffic Lights 3",
|
||||
"description": "Activity 3",
|
||||
"url":"/coding/traffic-lights-3",
|
||||
"cardType": "example"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Reverse Bepper
|
||||
|
||||
```codecard
|
||||
[{
|
||||
"name": "Reverse Beeper 1",
|
||||
"description": "Activity 1",
|
||||
"url":"/coding/reverse-beeper-1",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Reverse Beeper 2",
|
||||
"description": "Activity 2",
|
||||
"url":"/coding/reverse-beeper-2",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Reverse Beeper 3",
|
||||
"description": "Activity 3",
|
||||
"url":"/coding/reverse-beeper-3",
|
||||
"cardType": "example"
|
||||
}]
|
||||
```
|
||||
|
||||
## Ignition
|
||||
|
||||
```codecard
|
||||
[{
|
||||
"name": "Ignition 1",
|
||||
"description": "Activity 1",
|
||||
"url":"/coding/ingition-1",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Ignition 2",
|
||||
"description": "Activity 2",
|
||||
"url":"/coding/ignition-2",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Ignition 3",
|
||||
"description": "Activity 3",
|
||||
"url":"/coding/ignition-3",
|
||||
"cardType": "example"
|
||||
}]
|
||||
```
|
||||
|
||||
## Cruise Control
|
||||
|
||||
```codecard
|
||||
[{
|
||||
"name": "Cruise Control 1",
|
||||
"description": "Activity 1",
|
||||
"url":"/coding/cruise-control-1",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Cruise Control 2",
|
||||
"description": "Activity 2",
|
||||
"url":"/coding/cruise-control-2",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Cruise Control 3",
|
||||
"description": "Activity 3",
|
||||
"url":"/coding/cruise-control-3",
|
||||
"cardType": "example"
|
||||
}]
|
||||
```
|
||||
|
||||
## Roaming
|
||||
|
||||
```codecard
|
||||
[{
|
||||
"name": "Roaming 1",
|
||||
"description": "Activity 1",
|
||||
"url":"/coding/roaming-1",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Roaming 2",
|
||||
"description": "Activity 2",
|
||||
"url":"/coding/roaming-2",
|
||||
"cardType": "example"
|
||||
}]
|
||||
```
|
||||
|
||||
## Fun stuff
|
||||
|
||||
```codecard
|
||||
[
|
||||
{
|
||||
"name": "Happy unhappy",
|
||||
"description": "Keep your brick entertained and happy",
|
||||
"url":"/examples/happy-unhappy",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Turtle",
|
||||
"description": "Encode moves and run them on a driving base",
|
||||
"url":"/examples/turtle",
|
||||
"cardType": "example"
|
||||
}, {
|
||||
"name": "Distance Measurer",
|
||||
"description": "Use a motor to measure angle and distance",
|
||||
"url": "/examples/distance-measurer",
|
||||
"cardType": "example"
|
||||
}]
|
||||
```
|
||||
|
||||
Coming soon.
|
@ -1,178 +0,0 @@
|
||||
# Gyroboy
|
||||
|
||||
Work in progress
|
||||
|
||||
```blocks
|
||||
let motorSpeed1 = 0
|
||||
let motorSpeed2 = 0
|
||||
let motorSpeed3 = 0
|
||||
let motorSpeed = 0
|
||||
let fallen = false
|
||||
let motorSpeed0 = 0
|
||||
let oldControlDrive = 0
|
||||
let controlDrive = 0
|
||||
let power = 0
|
||||
let motorAngle = 0
|
||||
let gyroAngle = 0
|
||||
let controlSteering = 0
|
||||
let state = 0
|
||||
let motorPosition = 0
|
||||
let temp = 0
|
||||
let gyroRate = 0
|
||||
let timestep = 0
|
||||
sensors.color1.onColorDetected(ColorSensorColor.Red, function () {
|
||||
music.playTone(2000, 100)
|
||||
controlDrive = 0
|
||||
controlSteering = 0
|
||||
})
|
||||
// reads the motor angle and computes the motor speed,
|
||||
// position
|
||||
function computeMotors() {
|
||||
temp = motorAngle
|
||||
// read angle on both motors
|
||||
motorAngle = motors.largeD.angle() + motors.largeA.angle()
|
||||
// and estimate speed as angle difference
|
||||
motorSpeed0 = motorAngle - temp
|
||||
// average last 4 speed readings
|
||||
motorSpeed = (motorSpeed0 + motorSpeed1 + motorSpeed2 + motorSpeed3) / 4 / timestep
|
||||
// shift all previous recorded speeds by one
|
||||
motorSpeed3 = motorSpeed2
|
||||
motorSpeed2 = motorSpeed1
|
||||
motorSpeed1 = motorSpeed0
|
||||
// compute position from speed
|
||||
motorPosition = motorPosition + timestep * motorSpeed
|
||||
}
|
||||
// read the gyro rate and computes the angle
|
||||
function computeGyro() {
|
||||
gyroRate = sensors.gyro2.rate()
|
||||
gyroAngle = gyroAngle + timestep * gyroRate
|
||||
}
|
||||
function reset() {
|
||||
state = 0
|
||||
// sleeping
|
||||
moods.sleeping.show();
|
||||
// reset counters
|
||||
motors.largeA.reset()
|
||||
motors.largeD.reset()
|
||||
// motors are unregulated
|
||||
motors.largeA.setRegulated(false)
|
||||
motors.largeD.setRegulated(false)
|
||||
// clear the gyro sensor to remove drift
|
||||
sensors.gyro2.reset()
|
||||
// fall detection timer
|
||||
control.timer2.reset()
|
||||
// timestep computation timer
|
||||
control.timer3.reset()
|
||||
motorAngle = 0
|
||||
motorPosition = 0
|
||||
motorSpeed = 0
|
||||
motorSpeed0 = 0
|
||||
motorSpeed1 = 0
|
||||
motorSpeed2 = 0
|
||||
motorSpeed3 = 0
|
||||
gyroRate = 0
|
||||
gyroAngle = 0
|
||||
fallen = false
|
||||
power = 0
|
||||
controlSteering = 0
|
||||
controlDrive = 0
|
||||
// awake
|
||||
moods.awake.show();
|
||||
gyroAngle = -0.25
|
||||
state = 1;
|
||||
}
|
||||
// compute set point for motor position and required
|
||||
// motor power
|
||||
function computePower() {
|
||||
// apply control and compute desired motor position
|
||||
motorPosition -= timestep * controlDrive;
|
||||
// estimate power based on sensor readings and control
|
||||
// values
|
||||
power = 0.8 * gyroRate + 15 * gyroAngle + (0.08 * motorSpeed + 0.12 * motorPosition) - 0.01 * controlDrive
|
||||
// ensure that power stays within -100, 100
|
||||
if (power > 100) {
|
||||
power = 100
|
||||
} else if (power < -100) {
|
||||
power = -100
|
||||
}
|
||||
}
|
||||
// test if the robot has fallen off
|
||||
function checkFallen() {
|
||||
if (Math.abs(power) < 100) {
|
||||
control.timer2.reset()
|
||||
}
|
||||
if (control.timer2.seconds() > 2) {
|
||||
fallen = true
|
||||
}
|
||||
}
|
||||
// stop all motors and wait for touch button to be
|
||||
// pressed
|
||||
function stop() {
|
||||
motors.stopAll()
|
||||
state = 0
|
||||
moods.knockedOut.show();
|
||||
sensors.touch3.pauseUntil(ButtonEvent.Pressed)
|
||||
moods.neutral.show();
|
||||
}
|
||||
sensors.ultrasonic4.onEvent(UltrasonicSensorEvent.ObjectNear, function () {
|
||||
moods.dizzy.show()
|
||||
controlSteering = 0
|
||||
oldControlDrive = controlDrive
|
||||
controlDrive = -10
|
||||
motors.mediumC.run(30, 30, MoveUnit.Degrees);
|
||||
motors.mediumC.run(-30, 60, MoveUnit.Degrees);
|
||||
motors.mediumC.run(30, 30, MoveUnit.Degrees);
|
||||
if (Math.randomRange(-1, 1) >= 1) {
|
||||
controlSteering = 70
|
||||
} else {
|
||||
controlSteering = -70
|
||||
}
|
||||
pause(4000)
|
||||
music.playTone(2000, 100)
|
||||
controlSteering = 0
|
||||
controlDrive = oldControlDrive
|
||||
moods.neutral.show()
|
||||
})
|
||||
// compute the elapsed time since the last iteration
|
||||
function computeTimestep() {
|
||||
timestep = control.timer3.seconds()
|
||||
control.timer3.reset()
|
||||
}
|
||||
sensors.color1.onColorDetected(ColorSensorColor.Green, function () {
|
||||
moods.winking.show()
|
||||
controlDrive = 150
|
||||
controlSteering = 0
|
||||
})
|
||||
sensors.color1.onColorDetected(ColorSensorColor.Blue, function () {
|
||||
moods.middleRight.show()
|
||||
controlSteering = 70
|
||||
})
|
||||
// apply power to motors
|
||||
function controlMotors() {
|
||||
motors.largeA.run(power + controlSteering * 0.1)
|
||||
motors.largeD.run(power - controlSteering * 0.1)
|
||||
}
|
||||
sensors.color1.onColorDetected(ColorSensorColor.Yellow, function () {
|
||||
moods.middleLeft.show()
|
||||
controlSteering = -70
|
||||
})
|
||||
sensors.color1.onColorDetected(ColorSensorColor.White, function () {
|
||||
moods.sad.show();
|
||||
controlDrive = -75
|
||||
})
|
||||
timestep = 0.014
|
||||
// main loop
|
||||
forever(function () {
|
||||
reset()
|
||||
while (!fallen) {
|
||||
control.timer3.pauseUntil(5)
|
||||
computeTimestep()
|
||||
computeGyro()
|
||||
computeMotors()
|
||||
computePower()
|
||||
controlMotors()
|
||||
checkFallen()
|
||||
}
|
||||
stop()
|
||||
})
|
||||
```
|
@ -1,215 +0,0 @@
|
||||
# Gyroboy LabView
|
||||
|
||||
```typescript
|
||||
let mSum = 0;
|
||||
let mPos = 0;
|
||||
let mSpd = 0;
|
||||
let mD = 0;
|
||||
let mDP1 = 0;
|
||||
let mDP2 = 0;
|
||||
let mDP3 = 0;
|
||||
let Crdv = 0;
|
||||
let cLo = 0;
|
||||
let gAng = 0;
|
||||
let ok = false;
|
||||
let pwr = 0;
|
||||
let Cstr = 0;
|
||||
let Cdrv = 0;
|
||||
let gMn = 0;
|
||||
let gMx = 0;
|
||||
let gSum = 0;
|
||||
let gyro = 0;
|
||||
let gOS = 0;
|
||||
let gSpd = 0;
|
||||
let tInt = 0.014;
|
||||
let lpwr = 0
|
||||
let rpwr = 0
|
||||
let tStart = 0
|
||||
let st = 0
|
||||
let oldDr = 0
|
||||
|
||||
function RST() {
|
||||
motors.largeA.reset()
|
||||
motors.largeD.reset()
|
||||
motors.largeA.setRegulated(false)
|
||||
motors.largeD.setRegulated(false)
|
||||
sensors.gyro2.reset()
|
||||
sensors.gyro2.rate()
|
||||
control.timer2.reset()
|
||||
pause(5000)
|
||||
mSum = 0;
|
||||
mPos = 0;
|
||||
mD = 0;
|
||||
mDP1 = 0;
|
||||
mDP2 = 0;
|
||||
mDP3 = 0;
|
||||
Crdv = 0;
|
||||
cLo = 0;
|
||||
gAng = 0;
|
||||
ok = false;
|
||||
pwr = 0;
|
||||
st = 0;
|
||||
Cstr = 0;
|
||||
Cdrv = 0;
|
||||
}
|
||||
|
||||
function OS() {
|
||||
// OSL
|
||||
do {
|
||||
gMn = 1000;
|
||||
gMx = -100;
|
||||
gSum = 0;
|
||||
// gChk
|
||||
for (let i = 0; i < 200; i++) {
|
||||
gyro = sensors.gyro2.rate()
|
||||
gSum = gyro;
|
||||
gMx = Math.max(gMx, gyro)
|
||||
gMn = Math.min(gMn, gyro)
|
||||
pause(4);
|
||||
}
|
||||
} while (gMx - gMn > 2);
|
||||
gOS = gSum / 200;
|
||||
}
|
||||
|
||||
function GT() {
|
||||
if (cLo == 0) {
|
||||
tInt = 0.014;
|
||||
control.timer1.reset();
|
||||
} else {
|
||||
tInt = control.timer1.seconds() / cLo;
|
||||
}
|
||||
cLo++;
|
||||
}
|
||||
|
||||
function GG() {
|
||||
gyro = sensors.gyro2.rate();
|
||||
gOS = 0.0005 * gyro + (1 - 0.0005) * gOS
|
||||
gSpd = gyro - gOS;
|
||||
gAng = gAng + tInt * gSpd;
|
||||
}
|
||||
|
||||
function GM() {
|
||||
let temp = mSum
|
||||
mSum = motors.largeD.angle() + motors.largeA.angle();
|
||||
mD = mSum - temp;
|
||||
mPos = mPos + mD;
|
||||
mSpd = ((mDP1 + mDP2 + mDP3 + mD) / 4) / tInt;
|
||||
mDP3 = mDP2;
|
||||
mDP2 = mDP1;
|
||||
mDP1 = mD;
|
||||
}
|
||||
|
||||
function EQ() {
|
||||
mPos = mPos - Cdrv * tInt;
|
||||
pwr = (0.8 * gSpd + 15 * gAng) + (0.08 * mSpd + 0.12 * mPos) - 0.01 * Cdrv
|
||||
if (pwr > 100) pwr = 100
|
||||
else if (pwr < -100) pwr = -100
|
||||
}
|
||||
|
||||
function cntrl() {
|
||||
mPos = mPos - tInt * Cdrv
|
||||
lpwr = (pwr + Cstr * 0.1)
|
||||
rpwr = (pwr - Cstr * 0.1)
|
||||
}
|
||||
|
||||
function CHK() {
|
||||
if (Math.abs(pwr) < 100)
|
||||
control.timer2.reset();
|
||||
if (control.timer2.seconds() > 2) {
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
// M
|
||||
forever(function () {
|
||||
RST();
|
||||
brick.showImage(images.eyesSleeping)
|
||||
OS()
|
||||
gAng = -0.25;
|
||||
music.playSoundEffect(sounds.movementsSpeedUp)
|
||||
brick.showImage(images.eyesAwake)
|
||||
st = 1;
|
||||
// BALANCE
|
||||
while (!ok) {
|
||||
GT();
|
||||
let t1 = control.timer1.millis()
|
||||
GG();
|
||||
GM();
|
||||
EQ();
|
||||
cntrl();
|
||||
motors.largeA.run(lpwr)
|
||||
motors.largeD.run(rpwr)
|
||||
CHK()
|
||||
let t2 = control.timer1.millis();
|
||||
let p = 5 - (t2 - t1);
|
||||
pause(Math.max(1, p))
|
||||
}
|
||||
motors.stopAll()
|
||||
st = 0;
|
||||
brick.setStatusLight(StatusLight.RedPulse);
|
||||
brick.showImage(images.eyesKnockedOut)
|
||||
music.playSoundEffect(sounds.movementsSpeedDown)
|
||||
sensors.touch3.pauseUntil(ButtonEvent.Pressed)
|
||||
brick.setStatusLight(StatusLight.Off);
|
||||
})
|
||||
|
||||
// BHV
|
||||
forever(function () {
|
||||
switch (st) {
|
||||
case 0:
|
||||
Cdrv = 0;
|
||||
Cstr = 0;
|
||||
break;
|
||||
case 1:
|
||||
Cdrv = 40;
|
||||
pause(4000);
|
||||
Cdrv = 0;
|
||||
music.playTone(1000, 100);
|
||||
st = 2;
|
||||
break;
|
||||
case 2:
|
||||
switch (sensors.color1.color()) {
|
||||
case ColorSensorColor.Red:
|
||||
music.playTone(2000, 100);
|
||||
Cdrv = 0;
|
||||
Cstr = 0;
|
||||
break;
|
||||
case ColorSensorColor.Green:
|
||||
music.playTone(2000, 100);
|
||||
Cdrv = 150;
|
||||
Cstr = 0;
|
||||
break;
|
||||
case ColorSensorColor.Blue:
|
||||
music.playTone(2000, 100);
|
||||
Cstr = 70;
|
||||
break;
|
||||
case ColorSensorColor.Yellow:
|
||||
music.playTone(2000, 100);
|
||||
Cstr = -70;
|
||||
break;
|
||||
case ColorSensorColor.White:
|
||||
music.playTone(2000, 100);
|
||||
Cdrv = -75;
|
||||
break;
|
||||
}
|
||||
if (sensors.ultrasonic4.distance() < 25) {
|
||||
Cstr = 0;
|
||||
oldDr = Cdrv;
|
||||
Cdrv = -10;
|
||||
motors.mediumC.run(30, 30, MoveUnit.Degrees);
|
||||
motors.mediumC.run(-30, 60, MoveUnit.Degrees);
|
||||
motors.mediumC.run(30, 30, MoveUnit.Degrees);
|
||||
if (Math.randomRange(-1, 1) >= 1)
|
||||
Cstr = 70;
|
||||
else
|
||||
Cstr = -70;
|
||||
pause(4000);
|
||||
music.playTone(2000, 100)
|
||||
Cstr = 0;
|
||||
Cdrv = oldDr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
pause(80);
|
||||
})
|
||||
```
|
@ -1,390 +0,0 @@
|
||||
# Puppy
|
||||
|
||||
```typescript
|
||||
let P_T = 0;
|
||||
let ISS = 0;
|
||||
let F_T = 0;
|
||||
let P_C = 0;
|
||||
let F_C = 0;
|
||||
let DB_S = 0;
|
||||
let NS = false;
|
||||
let IBP = 0;
|
||||
let IAP = 0;
|
||||
let C = false;
|
||||
let TC = false;
|
||||
let OTC = false;
|
||||
let COL = 0;
|
||||
let OCOL = 0;
|
||||
let _C = false;
|
||||
let GTO = 0;
|
||||
|
||||
function DN() {
|
||||
motors.largeAD.setBrake(true);
|
||||
motors.largeAD.tank(50, 50, 1, MoveUnit.Seconds);
|
||||
pause(100);
|
||||
motors.largeA.clearCounts()
|
||||
motors.largeD.clearCounts()
|
||||
}
|
||||
|
||||
function MNRH() {
|
||||
motors.mediumC.setBrake(true)
|
||||
brick.showImage(images.legoEv3icon)
|
||||
brick.setStatusLight(StatusLight.OrangePulse)
|
||||
while (!brick.buttonEnter.wasPressed()) {
|
||||
if (brick.buttonUp.wasPressed()) {
|
||||
motors.mediumC.run(-100);
|
||||
} else if (brick.buttonDown.wasPressed()) {
|
||||
motors.mediumC.run(100);
|
||||
} else {
|
||||
motors.mediumC.stop();
|
||||
}
|
||||
}
|
||||
motors.mediumC.stop();
|
||||
motors.mediumC.clearCounts();
|
||||
brick.setStatusLight(StatusLight.Green);
|
||||
}
|
||||
|
||||
function IS(t: number) {
|
||||
ISS = t;
|
||||
switch (t) {
|
||||
case 0:
|
||||
brick.showImage(images.eyesNeutral);
|
||||
break;
|
||||
case 1:
|
||||
brick.showImage(images.eyesSleeping);
|
||||
break;
|
||||
case 2:
|
||||
brick.showImage(images.eyesTear);
|
||||
// draw rect...
|
||||
break;
|
||||
case 3:
|
||||
brick.showImage(images.eyesHurt);
|
||||
break;
|
||||
case 4:
|
||||
brick.showImage(images.eyesAngry);
|
||||
break;
|
||||
case 5:
|
||||
brick.showImage(images.eyesTiredMiddle);
|
||||
break;
|
||||
case 6:
|
||||
brick.showImage(images.eyesTiredRight);
|
||||
break;
|
||||
case 7:
|
||||
brick.showImage(images.eyesTiredLeft);
|
||||
break;
|
||||
case 8:
|
||||
brick.showImage(images.eyesLove);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function UP() {
|
||||
if (motors.largeA.angle() > -50) {
|
||||
control.runInParallel(function () {
|
||||
motors.largeD.clearCounts()
|
||||
motors.largeD.run(-35);
|
||||
pauseUntil(() => motors.largeD.angle() < -25);
|
||||
motors.largeD.stop();
|
||||
motors.largeD.setRegulated(false)
|
||||
motors.largeD.run(-15)
|
||||
pauseUntil(() => motors.largeD.angle() < -65);
|
||||
motors.largeD.stop();
|
||||
})
|
||||
motors.largeA.clearCounts()
|
||||
motors.largeA.run(-35);
|
||||
pauseUntil(() => motors.largeA.angle() < -25);
|
||||
motors.largeA.stop();
|
||||
motors.largeA.setRegulated(false)
|
||||
motors.largeA.run(-15)
|
||||
pauseUntil(() => motors.largeA.angle() < -65);
|
||||
motors.largeA.stop();
|
||||
|
||||
pause(500);
|
||||
}
|
||||
}
|
||||
|
||||
function RST() {
|
||||
P_T = Math.randomRange(3, 6);
|
||||
F_T = Math.randomRange(2, 4);
|
||||
P_C = 1;
|
||||
F_C = 1;
|
||||
control.timer1.reset();
|
||||
control.timer2.reset();
|
||||
control.timer3.reset();
|
||||
CS(0);
|
||||
}
|
||||
|
||||
function CS(db: number) {
|
||||
if (DB_S != db) {
|
||||
DB_S = db;
|
||||
NS = true;
|
||||
}
|
||||
}
|
||||
|
||||
function MON() {
|
||||
if (control.timer2.seconds() > 10) {
|
||||
control.timer2.reset();
|
||||
P_C--;
|
||||
if (P_C < 0) {
|
||||
P_C = 0;
|
||||
}
|
||||
}
|
||||
if (control.timer1.seconds() > 20) {
|
||||
control.timer1.reset()
|
||||
F_C--;
|
||||
if (F_C < 0) {
|
||||
F_C = 0;
|
||||
}
|
||||
}
|
||||
if (control.timer3.seconds() > 30) {
|
||||
control.timer3.reset();
|
||||
CS(1);
|
||||
}
|
||||
}
|
||||
|
||||
function UIS() {
|
||||
if (control.timer5.seconds() > IBP) {
|
||||
control.timer5.reset();
|
||||
if (ISS == 1) {
|
||||
ISS = 6;
|
||||
IBP = Math.randomRange(1, 5);
|
||||
} else {
|
||||
ISS = 1;
|
||||
IBP = 0.25;
|
||||
}
|
||||
IS(ISS);
|
||||
}
|
||||
if (control.timer6.seconds() > IAP) {
|
||||
if (ISS != 1) {
|
||||
control.timer6.reset();
|
||||
IAP = Math.randomRange(1, 10)
|
||||
if (ISS != 7) {
|
||||
ISS = 7
|
||||
} else {
|
||||
ISS = 6;
|
||||
}
|
||||
IS(ISS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function UPDB() {
|
||||
if ((P_T == P_C) && (F_T == F_C)) {
|
||||
CS(6);
|
||||
}
|
||||
if ((P_T > P_C) && (F_T < F_C)) {
|
||||
CS(3);
|
||||
}
|
||||
if ((P_T < P_C) && (F_T > F_C)) {
|
||||
CS(5);
|
||||
}
|
||||
if ((P_C == 0) && (F_C > 0)) {
|
||||
CS(2)
|
||||
}
|
||||
if (F_C == 0) {
|
||||
CS(4)
|
||||
}
|
||||
}
|
||||
|
||||
function PTC() {
|
||||
C = false;
|
||||
OTC = TC;
|
||||
TC = sensors.touch1.isPressed()
|
||||
if (TC != OTC && TC) {
|
||||
P_C++;
|
||||
control.timer3.reset();
|
||||
if (DB_S != 4) {
|
||||
IS(2);
|
||||
music.playSoundEffect(sounds.animalsDogSniff);
|
||||
C = true;
|
||||
}
|
||||
}
|
||||
return C;
|
||||
}
|
||||
|
||||
function FDC() {
|
||||
OCOL = COL;
|
||||
COL = sensors.color4.color();
|
||||
_C = false;
|
||||
if ((COL != 0) && (OCOL != COL)) {
|
||||
F_C++;
|
||||
_C = true;
|
||||
control.timer3.reset();
|
||||
IS(2);
|
||||
music.playSoundEffect(sounds.expressionsCrunching)
|
||||
}
|
||||
return _C;
|
||||
}
|
||||
|
||||
function IDL() {
|
||||
if (NS) {
|
||||
NS = false;
|
||||
UP();
|
||||
}
|
||||
UIS();
|
||||
UPDB();
|
||||
PTC();
|
||||
FDC();
|
||||
}
|
||||
|
||||
function MHT(Pos: number) {
|
||||
let _R = Pos - motors.mediumC.angle();
|
||||
if (_R >= 0) {
|
||||
motors.mediumC.run(100, _R, MoveUnit.Degrees);
|
||||
} else {
|
||||
motors.mediumC.run(-100, Math.abs(_R), MoveUnit.Degrees);
|
||||
}
|
||||
}
|
||||
|
||||
function SLP() {
|
||||
if (NS) {
|
||||
NS = false;
|
||||
IS(5)
|
||||
DN()
|
||||
MHT(3000)
|
||||
IS(1)
|
||||
music.playSoundEffect(sounds.expressionsSnoring)
|
||||
}
|
||||
if (sensors.touch1.isPressed() || brick.buttonEnter.isPressed()) {
|
||||
music.stopAllSounds();
|
||||
control.timer3.reset();
|
||||
CS(7);
|
||||
}
|
||||
}
|
||||
|
||||
function PLF() {
|
||||
if (NS) {
|
||||
NS = false
|
||||
IS(0)
|
||||
UP()
|
||||
music.playSoundEffect(sounds.animalsDogBark2)
|
||||
control.timer4.reset()
|
||||
GTO = Math.randomRange(4, 8);
|
||||
}
|
||||
if(PTC()) {
|
||||
CS(0);
|
||||
}
|
||||
if (control.timer4.seconds() > GTO) {
|
||||
music.playSoundEffect(sounds.animalsDogBark2)
|
||||
control.timer4.reset();
|
||||
GTO = Math.randomRange(4, 8);
|
||||
}
|
||||
}
|
||||
|
||||
function NGR() {
|
||||
NS = false
|
||||
IS(4)
|
||||
music.playSoundEffect(sounds.animalsDogGrowl);
|
||||
UP();
|
||||
pause(1500);
|
||||
music.stopAllSounds()
|
||||
music.playSoundEffect(sounds.animalsDogBark1)
|
||||
P_C--;
|
||||
CS(0);
|
||||
}
|
||||
|
||||
function HNG() {
|
||||
if (NS) {
|
||||
NS = false;
|
||||
IS(3)
|
||||
DN();
|
||||
music.playSoundEffect(sounds.animalsDogWhine);
|
||||
}
|
||||
if(FDC()) {
|
||||
CS(0)
|
||||
}
|
||||
if (PTC()) {
|
||||
CS(3);
|
||||
}
|
||||
}
|
||||
|
||||
function PPP() {
|
||||
NS = false;
|
||||
IS(2);
|
||||
UP();
|
||||
pause(100)
|
||||
motors.largeA.run(-30, 70, MoveUnit.Degrees);
|
||||
pause(800);
|
||||
music.playSoundEffect(sounds.mechanicalHorn1);
|
||||
pause(1000);
|
||||
for(let i = 0; i < 3; ++i) {
|
||||
motors.largeA.run(-30, 20, MoveUnit.Degrees);
|
||||
motors.largeA.run(30, 20, MoveUnit.Degrees);
|
||||
}
|
||||
motors.largeA.run(30, 70, MoveUnit.Degrees);
|
||||
F_C = 1;
|
||||
CS(0);
|
||||
}
|
||||
|
||||
function HPY() {
|
||||
IS(8)
|
||||
MHT(0);
|
||||
motors.largeAD.run(10, 0.8, MoveUnit.Seconds);
|
||||
for(let i = 0; i < 3; ++i) {
|
||||
music.playSoundEffect(sounds.animalsDogBark1);
|
||||
motors.largeAD.run(-100, 0.2, MoveUnit.Seconds);
|
||||
pause(300)
|
||||
motors.largeAD.run(10, 0.3, MoveUnit.Seconds)
|
||||
}
|
||||
pause(500);
|
||||
music.stopAllSounds();
|
||||
DN();
|
||||
RST();
|
||||
}
|
||||
|
||||
function STL() {
|
||||
UP();
|
||||
motors.largeAD.run(-20, 60, MoveUnit.Degrees);
|
||||
music.playSoundEffect(sounds.animalsDogWhine);
|
||||
motors.largeAD.run(20, 60, MoveUnit.Degrees);
|
||||
}
|
||||
|
||||
function WKU() {
|
||||
let stateC = false;
|
||||
IS(5);
|
||||
music.playSoundEffect(sounds.animalsDogWhine)
|
||||
MHT(0)
|
||||
DN()
|
||||
STL()
|
||||
pause(1000);
|
||||
UP()
|
||||
CS(0;)
|
||||
}
|
||||
|
||||
DN();
|
||||
MNRH();
|
||||
// compare button state???
|
||||
IS(1);
|
||||
UP();
|
||||
RST();
|
||||
forever(function () {
|
||||
MON();
|
||||
switch (DB_S) {
|
||||
case 0:
|
||||
IDL();
|
||||
break;
|
||||
case 1:
|
||||
SLP();
|
||||
break;
|
||||
case 2:
|
||||
PLF();
|
||||
break;
|
||||
case 3:
|
||||
NGR();
|
||||
break;
|
||||
case 4:
|
||||
HNG();
|
||||
break;
|
||||
case 5:
|
||||
PPP();
|
||||
break;
|
||||
case 6:
|
||||
HPY();
|
||||
break;
|
||||
case 7:
|
||||
WKU();
|
||||
break;
|
||||
}
|
||||
})
|
||||
```
|
@ -1,51 +0,0 @@
|
||||
# Robot Arm
|
||||
|
||||
```typescript
|
||||
function INI() {
|
||||
motors.largeB.setBrake(true)
|
||||
motors.largeC.setBrake(true)
|
||||
motors.mediumA.setBrake(true)
|
||||
motors.largeB.run(-50)
|
||||
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
|
||||
motors.largeB.stop();
|
||||
motors.mediumA.run(30, 1, MoveUnit.Seconds);
|
||||
motors.mediumA.run(-50, 90, MoveUnit.Degrees);
|
||||
motors.largeC.run(50)
|
||||
sensors.touch1.pauseUntil(ButtonEvent.Pressed);
|
||||
motors.largeC.run(-50, 0.86, MoveUnit.Rotations);
|
||||
}
|
||||
|
||||
INI()
|
||||
|
||||
let down = false;
|
||||
forever(function () {
|
||||
brick.showImage(images.informationQuestionMark)
|
||||
brick.setStatusLight(StatusLight.OrangePulse);
|
||||
pauseUntil(() => (down = brick.buttonDown.wasPressed()) || brick.buttonUp.wasPressed())
|
||||
brick.setStatusLight(StatusLight.Off)
|
||||
music.playSoundEffect(sounds.mechanicalAirRelease)
|
||||
brick.showImage(images.informationAccept)
|
||||
if (down) {
|
||||
brick.showImage(images.informationForward)
|
||||
motors.largeC.run(65, 0.85, MoveUnit.Rotations);
|
||||
} else {
|
||||
brick.showImage(images.informationBackward)
|
||||
motors.largeC.run(-65, 0.85, MoveUnit.Rotations);
|
||||
}
|
||||
motors.largeB.run(20, 275, MoveUnit.Degrees)
|
||||
motors.mediumA.run(30, 1, MoveUnit.Seconds)
|
||||
motors.largeB.run(-55)
|
||||
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
|
||||
motors.largeB.stop();
|
||||
if (down) {
|
||||
motors.largeC.run(-65, 0.86, MoveUnit.Rotations);
|
||||
} else {
|
||||
motors.largeC.run(65, 0.85, MoveUnit.Rotations);
|
||||
}
|
||||
motors.largeB.run(20, 275, MoveUnit.Degrees);
|
||||
motors.mediumA.run(-30, 90, MoveUnit.Degrees);
|
||||
motors.largeB.run(-55)
|
||||
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
|
||||
motors.largeB.stop()
|
||||
})
|
||||
```
|
@ -1,51 +0,0 @@
|
||||
# Crane LabView
|
||||
|
||||
```blocks
|
||||
function INI() {
|
||||
motors.largeB.setBrake(true)
|
||||
motors.largeC.setBrake(true)
|
||||
motors.mediumA.setBrake(true)
|
||||
motors.largeB.run(-50)
|
||||
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
|
||||
motors.largeB.stop();
|
||||
motors.mediumA.run(30, 1, MoveUnit.Seconds);
|
||||
motors.mediumA.run(-50, 90, MoveUnit.Degrees);
|
||||
motors.largeC.run(50)
|
||||
sensors.touch1.pauseUntil(ButtonEvent.Pressed);
|
||||
motors.largeC.run(-50, 0.86, MoveUnit.Rotations);
|
||||
}
|
||||
|
||||
INI()
|
||||
|
||||
let down = false;
|
||||
forever(function () {
|
||||
brick.showImage(images.informationQuestionMark)
|
||||
brick.setStatusLight(StatusLight.OrangePulse);
|
||||
pauseUntil(() => (down = brick.buttonDown.wasPressed()) || brick.buttonUp.wasPressed())
|
||||
brick.setStatusLight(StatusLight.Off)
|
||||
music.playSoundEffect(sounds.mechanicalAirRelease)
|
||||
brick.showImage(images.informationAccept)
|
||||
if (down) {
|
||||
brick.showImage(images.informationForward)
|
||||
motors.largeC.run(65, 0.85, MoveUnit.Rotations);
|
||||
} else {
|
||||
brick.showImage(images.informationBackward)
|
||||
motors.largeC.run(-65, 0.85, MoveUnit.Rotations);
|
||||
}
|
||||
motors.largeB.run(20, 275, MoveUnit.Degrees)
|
||||
motors.mediumA.run(30, 1, MoveUnit.Seconds)
|
||||
motors.largeB.run(-55)
|
||||
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
|
||||
motors.largeB.stop();
|
||||
if (down) {
|
||||
motors.largeC.run(-65, 0.86, MoveUnit.Rotations);
|
||||
} else {
|
||||
motors.largeC.run(65, 0.85, MoveUnit.Rotations);
|
||||
}
|
||||
motors.largeB.run(20, 275, MoveUnit.Degrees);
|
||||
motors.mediumA.run(-30, 90, MoveUnit.Degrees);
|
||||
motors.largeB.run(-55)
|
||||
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
|
||||
motors.largeB.stop()
|
||||
})
|
||||
```
|
@ -1,34 +0,0 @@
|
||||
# Distance Measurer
|
||||
|
||||
```blocks
|
||||
let distance = 0
|
||||
let angle = 0
|
||||
let measuring = false
|
||||
let radius = 0
|
||||
// Start and stop measuring with the enter button
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
if (measuring) {
|
||||
// turn off the measuring
|
||||
measuring = false
|
||||
brick.setStatusLight(StatusLight.Off)
|
||||
} else {
|
||||
// turn on the measuring clear the counters so that
|
||||
// the motor tracks the angle
|
||||
measuring = true
|
||||
motors.largeB.clearCounts()
|
||||
brick.setStatusLight(StatusLight.GreenPulse)
|
||||
}
|
||||
})
|
||||
radius = 2.5
|
||||
brick.showString("Press ENTER to measure", 4)
|
||||
forever(function () {
|
||||
if (measuring) {
|
||||
angle = motors.largeB.angle()
|
||||
distance = angle / 180 * Math.PI * radius
|
||||
brick.clearScreen()
|
||||
brick.showValue("angle", angle, 2)
|
||||
brick.showValue("distance", distance, 3)
|
||||
}
|
||||
pause(100)
|
||||
})
|
||||
```
|
@ -1,215 +0,0 @@
|
||||
# Gyro Boy LabView
|
||||
|
||||
```blocks
|
||||
let mSum = 0;
|
||||
let mPos = 0;
|
||||
let mSpd = 0;
|
||||
let mD = 0;
|
||||
let mDP1 = 0;
|
||||
let mDP2 = 0;
|
||||
let mDP3 = 0;
|
||||
let Crdv = 0;
|
||||
let cLo = 0;
|
||||
let gAng = 0;
|
||||
let ok = false;
|
||||
let pwr = 0;
|
||||
let Cstr = 0;
|
||||
let Cdrv = 0;
|
||||
let gMn = 0;
|
||||
let gMx = 0;
|
||||
let gSum = 0;
|
||||
let gyro = 0;
|
||||
let gOS = 0;
|
||||
let gSpd = 0;
|
||||
let tInt = 0.014;
|
||||
let lpwr = 0
|
||||
let rpwr = 0
|
||||
let tStart = 0
|
||||
let st = 0
|
||||
let oldDr = 0
|
||||
|
||||
function RST() {
|
||||
motors.largeA.reset()
|
||||
motors.largeD.reset()
|
||||
motors.largeA.setRegulated(false)
|
||||
motors.largeD.setRegulated(false)
|
||||
sensors.gyro2.reset()
|
||||
sensors.gyro2.rate()
|
||||
control.timer2.reset()
|
||||
pause(5000)
|
||||
mSum = 0;
|
||||
mPos = 0;
|
||||
mD = 0;
|
||||
mDP1 = 0;
|
||||
mDP2 = 0;
|
||||
mDP3 = 0;
|
||||
Crdv = 0;
|
||||
cLo = 0;
|
||||
gAng = 0;
|
||||
ok = false;
|
||||
pwr = 0;
|
||||
st = 0;
|
||||
Cstr = 0;
|
||||
Cdrv = 0;
|
||||
}
|
||||
|
||||
function OS() {
|
||||
// OSL
|
||||
do {
|
||||
gMn = 1000;
|
||||
gMx = -100;
|
||||
gSum = 0;
|
||||
// gChk
|
||||
for (let i = 0; i < 200; i++) {
|
||||
gyro = sensors.gyro2.rate()
|
||||
gSum = gyro;
|
||||
gMx = Math.max(gMx, gyro)
|
||||
gMn = Math.min(gMn, gyro)
|
||||
pause(4);
|
||||
}
|
||||
} while (gMx - gMn > 2);
|
||||
gOS = gSum / 200;
|
||||
}
|
||||
|
||||
function GT() {
|
||||
if (cLo == 0) {
|
||||
tInt = 0.014;
|
||||
control.timer1.reset();
|
||||
} else {
|
||||
tInt = control.timer1.seconds() / cLo;
|
||||
}
|
||||
cLo++;
|
||||
}
|
||||
|
||||
function GG() {
|
||||
gyro = sensors.gyro2.rate();
|
||||
gOS = 0.0005 * gyro + (1 - 0.0005) * gOS
|
||||
gSpd = gyro - gOS;
|
||||
gAng = gAng + tInt * gSpd;
|
||||
}
|
||||
|
||||
function GM() {
|
||||
let temp = mSum
|
||||
mSum = motors.largeD.angle() + motors.largeA.angle();
|
||||
mD = mSum - temp;
|
||||
mPos = mPos + mD;
|
||||
mSpd = ((mDP1 + mDP2 + mDP3 + mD) / 4) / tInt;
|
||||
mDP3 = mDP2;
|
||||
mDP2 = mDP1;
|
||||
mDP1 = mD;
|
||||
}
|
||||
|
||||
function EQ() {
|
||||
mPos = mPos - Cdrv * tInt;
|
||||
pwr = (0.8 * gSpd + 15 * gAng) + (0.095 * mSpd + 0.13 * mPos) - 0.01 * Cdrv
|
||||
if (pwr > 100) pwr = 100
|
||||
else if (pwr < -100) pwr = -100
|
||||
}
|
||||
|
||||
function cntrl() {
|
||||
mPos = mPos - tInt * Cdrv
|
||||
lpwr = (pwr + Cstr * 0.1)
|
||||
rpwr = (pwr - Cstr * 0.1)
|
||||
}
|
||||
|
||||
function CHK() {
|
||||
if (Math.abs(pwr) < 100)
|
||||
control.timer2.reset();
|
||||
if (control.timer2.seconds() > 2) {
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
// M
|
||||
forever(function () {
|
||||
RST();
|
||||
brick.showImage(images.eyesSleeping)
|
||||
OS()
|
||||
gAng = -0.25;
|
||||
music.playSoundEffect(sounds.movementsSpeedUp)
|
||||
brick.showImage(images.eyesAwake)
|
||||
st = 1;
|
||||
// BALANCE
|
||||
while (!ok) {
|
||||
GT();
|
||||
let t1 = control.timer1.millis()
|
||||
GG();
|
||||
GM();
|
||||
EQ();
|
||||
cntrl();
|
||||
motors.largeA.run(lpwr)
|
||||
motors.largeD.run(rpwr)
|
||||
CHK()
|
||||
let t2 = control.timer1.millis();
|
||||
let p = 5 - (t2 - t1);
|
||||
pause(Math.max(1, p))
|
||||
}
|
||||
motors.stopAll()
|
||||
st = 0;
|
||||
brick.setStatusLight(StatusLight.RedPulse);
|
||||
brick.showImage(images.eyesKnockedOut)
|
||||
music.playSoundEffect(sounds.movementsSpeedDown)
|
||||
sensors.touch3.pauseUntil(ButtonEvent.Pressed)
|
||||
brick.setStatusLight(StatusLight.Off);
|
||||
})
|
||||
|
||||
// BHV
|
||||
forever(function () {
|
||||
switch (st) {
|
||||
case 0:
|
||||
Cdrv = 0;
|
||||
Cstr = 0;
|
||||
break;
|
||||
case 1:
|
||||
Cdrv = 40;
|
||||
pause(4000);
|
||||
Cdrv = 0;
|
||||
music.playTone(1000, 100);
|
||||
st = 2;
|
||||
break;
|
||||
case 2:
|
||||
switch (sensors.color1.color()) {
|
||||
case ColorSensorColor.Red:
|
||||
music.playTone(2000, 100);
|
||||
Cdrv = 0;
|
||||
Cstr = 0;
|
||||
break;
|
||||
case ColorSensorColor.Green:
|
||||
music.playTone(2000, 100);
|
||||
Cdrv = 150;
|
||||
Cstr = 0;
|
||||
break;
|
||||
case ColorSensorColor.Blue:
|
||||
music.playTone(2000, 100);
|
||||
Cstr = 70;
|
||||
break;
|
||||
case ColorSensorColor.Yellow:
|
||||
music.playTone(2000, 100);
|
||||
Cstr = -70;
|
||||
break;
|
||||
case ColorSensorColor.White:
|
||||
music.playTone(2000, 100);
|
||||
Cdrv = -75;
|
||||
break;
|
||||
}
|
||||
if (sensors.ultrasonic4.distance() < 25) {
|
||||
Cstr = 0;
|
||||
oldDr = Cdrv;
|
||||
Cdrv = -10;
|
||||
motors.mediumC.run(30, 30, MoveUnit.Degrees);
|
||||
motors.mediumC.run(-30, 60, MoveUnit.Degrees);
|
||||
motors.mediumC.run(30, 30, MoveUnit.Degrees);
|
||||
if (Math.randomRange(-1, 1) >= 1)
|
||||
Cstr = 70;
|
||||
else
|
||||
Cstr = -70;
|
||||
pause(4000);
|
||||
music.playTone(2000, 100)
|
||||
Cstr = 0;
|
||||
Cdrv = oldDr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
pause(80);
|
||||
})
|
||||
```
|
@ -1,12 +0,0 @@
|
||||
# Happy unhappy
|
||||
|
||||
Use a touch sensor to make the brick happy.
|
||||
|
||||
```blocks
|
||||
sensors.touch1.onEvent(ButtonEvent.Pressed, function () {
|
||||
brick.showImage(images.expressionsBigSmile)
|
||||
})
|
||||
sensors.touch1.onEvent(ButtonEvent.Released, function () {
|
||||
brick.showImage(images.expressionsSick)
|
||||
})
|
||||
```
|
@ -1,50 +0,0 @@
|
||||
# Gradien follower PID + calibration
|
||||
|
||||
```blocks
|
||||
let lasterror = 0
|
||||
let D = 0
|
||||
let I = 0
|
||||
let P = 0
|
||||
let error = 0
|
||||
let setpoint = 0
|
||||
let max = 0
|
||||
let min = 0
|
||||
let v = 0
|
||||
v = sensors.color3.light(LightIntensityMode.Reflected)
|
||||
min = v
|
||||
max = v
|
||||
setpoint = v
|
||||
while (!(brick.buttonEnter.isPressed())) {
|
||||
brick.clearScreen()
|
||||
brick.showString("Move robot on terrain", 1)
|
||||
brick.showString("Press ENTER when done", 2)
|
||||
v = sensors.color3.light(LightIntensityMode.Reflected)
|
||||
min = Math.min(min, v)
|
||||
max = Math.max(max, v)
|
||||
setpoint = (max + min) / 2
|
||||
brick.showValue("v", v, 3)
|
||||
brick.showValue("min", min, 4)
|
||||
brick.showValue("max", v, 5)
|
||||
brick.showValue("setpoint", setpoint, 6)
|
||||
pause(100)
|
||||
}
|
||||
forever(function () {
|
||||
brick.clearScreen()
|
||||
v = sensors.color3.light(LightIntensityMode.Reflected)
|
||||
brick.showValue("light", v, 1)
|
||||
error = v - setpoint
|
||||
brick.showValue("error", error, 2)
|
||||
P = error * 5
|
||||
brick.showValue("P", P, 3)
|
||||
I = I + error * 0.01
|
||||
brick.showValue("I", I, 4)
|
||||
D = (error - lasterror) * 0.2
|
||||
brick.showValue("D", D, 5)
|
||||
motors.largeBC.steer(P + (I + D), 100)
|
||||
lasterror = error
|
||||
if (brick.buttonEnter.wasPressed()) {
|
||||
motors.largeBC.run(0)
|
||||
brick.buttonDown.pauseUntil(ButtonEvent.Bumped)
|
||||
}
|
||||
})
|
||||
```
|
@ -1,18 +0,0 @@
|
||||
# Extensions
|
||||
|
||||
## #gallery
|
||||
|
||||
## Using Extensions
|
||||
|
||||
In the web editor, click on ``Settings`` then ``Extensions`` to search and add extensions to the project.
|
||||
The Blocks and JavaScript definitions will be automatically loaded in the editor.
|
||||
|
||||
## Custom extensions
|
||||
|
||||
The [Build Your Own Extension](https://makecode.com/extensions/getting-started) manual is for advanced users who want to publish their own extension.
|
||||
|
||||
## ~ hint
|
||||
|
||||
**Extensions** were previously called **Packages** in MakeCode.
|
||||
|
||||
## ~
|
Binary file not shown.
134
docs/fll.md
134
docs/fll.md
@ -1,134 +0,0 @@
|
||||
# MakeCode for _FIRST_ LEGO League
|
||||
|
||||
![FIRST LEGO League logo](/static/fll/fll-logo.png)
|
||||
|
||||
**For teams participating in City Shaper challenge**, you can use MakeCode for your challenge (see [City Shaper Challenge, page 7 bottom](https://firstinspiresst01.blob.core.windows.net/fll/2020/city-shaper-game-guide-pdf.pdf)!
|
||||
|
||||
We’ve compiled a list of resources and information that we hope will be helpful for you.
|
||||
|
||||
* **Got a question? Post it on the forums** at https://forum.makecode.com/
|
||||
|
||||
## FAQ
|
||||
|
||||
### I found a bug what do I do?
|
||||
|
||||
If you found a bug, please try if it hasn't been fixed yet! Go to https://makecode.mindstorms.com/beta and try if the bug is corrected. Otherwise, please tell us at https://forum.makecode.com/.
|
||||
|
||||
### How do I use MakeCode with my EV3?
|
||||
|
||||
* You will need to install the latest EV3 firmware on your brick. Instructions on how to do that are located here: https://makecode.mindstorms.com/troubleshoot.
|
||||
* You will need a computer with a USB port to connect to the EV3 in order to download your programs.
|
||||
* You will need internet access and a browser on your computer to get to https://makecode.mindstorms.com.
|
||||
* You can [install the app](/offline-app) to use the editor offline.
|
||||
|
||||
### I know LabView, how is MakeCode different?
|
||||
|
||||
We have compiled a guide for EV3 LabView users at https://makecode.mindstorms.com/labview.
|
||||
|
||||
### What’s the best way to get started with MakeCode?
|
||||
|
||||
Go to https://makecode.mindstorms.com. The home screen is filled with videos, tutorials and examples that might be relevant for your missions.
|
||||
|
||||
On the home page, scroll down to the **FLL / City Shaper** section for specific lessons related to Mission 2.
|
||||
|
||||
### Can I load both LEGO MINDSTORMS EV3 Software and MakeCode programs onto my EV3?
|
||||
|
||||
Yes.
|
||||
|
||||
### Can I run the program again on the brick?
|
||||
|
||||
![EV3 Brick with Try in BrkProg_Save Folder in File Manager](/static/getting-started/try-in-file-manager.png)
|
||||
|
||||
Use the Brick Buttons and navigate to the File Manager tab. Open the **BrkProg_SAVE** folder,
|
||||
select your program and click the center button to run it again.
|
||||
|
||||
### Does it work without internet?
|
||||
|
||||
No, the editor is cached in your browser cache. However, you can also download the [offline app](/offline-app) in case you need to install it on a computer.
|
||||
|
||||
### How do I figure out what a block does?
|
||||
|
||||
You can right-click on any block and select “Help” in the context menu to open the documentation page describing what that block does.
|
||||
|
||||
![Select help in context menu for block](/static/fll/context-help.jpg)
|
||||
|
||||
### How do I program in JavaScript?
|
||||
|
||||
Click the **JavaScript** button at the top of the page to get to the JavaScript editor. Students can drag and drop code snippets from the Toolbox on the left, or type directly in the editor. You can switch back and forth between **Blocks** and **JavaScript** as you program.
|
||||
|
||||
![Coding in JavaScript](/static/fll/code-js.gif)
|
||||
|
||||
Also, watch the [Text-based Coding](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=3513a83b87fe536b2dc512237465fd1b&source=embed&photo%5fid=35719471) video for more about coding using the JavaScript editor.
|
||||
|
||||
### How do I use the Simulator?
|
||||
|
||||
The Simulator will show the physical representation of your code blocks. For example, based on this code snippet, the Simulator will show the touch sensor on Port 1, and a large motor on Port D.
|
||||
|
||||
```blocks
|
||||
sensors.touch1.onEvent(ButtonEvent.Pressed, function () {
|
||||
motors.largeD.run(50)
|
||||
})
|
||||
```
|
||||
|
||||
![Simulator demonstration](/static/fll/simulator.gif)
|
||||
|
||||
Note that the Simulator is also interactive, so you can simulate inputs with any of the sensors.
|
||||
|
||||
See the video [Block-based Coding and Simulation](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=629730c938e452f0fd7653fbc4708166&source=embed&photo%5fid=35719470) for more about using the simulator.
|
||||
|
||||
### How do I save my programs?
|
||||
|
||||
MakeCode will automatically save your recent projects in the browser. However, you can also save a copy of your project as a file on your computer:
|
||||
|
||||
* From the **Settings** menu, select **Save Project**
|
||||
* This will download your program from the browser as a _lego-myproject.uf2_ file
|
||||
|
||||
![Save project menu selection](/static/fll/save-project.jpg)
|
||||
|
||||
* You can import your saved projects by clicking the Import button on the Home Page
|
||||
|
||||
![Import button on home screen](/static/fll/import-button.jpg)
|
||||
|
||||
### How do I share my programs?
|
||||
|
||||
You can share your projects by clicking on the **share** button in the top left of the screen. This will create a URL which you can send others to open and view your project.
|
||||
|
||||
![Share button in editor](/static/fll/share-button.jpg)
|
||||
|
||||
![Share button and dialogs demo](/static/fll/share-program.gif)
|
||||
|
||||
Sharing programs is also shown in the [Tips and Tricks](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=5c594c2373367f7870196f519f3bfc7a&source=embed&photo%5fid=35719472) video.
|
||||
|
||||
### Can I use Bluetooth to transfer my program?
|
||||
|
||||
The official answer is currently no. That being said, we have **Experimental support** for Bluetooth download. Please read the [Bluetooth](/bluetooth) page for more information.
|
||||
|
||||
https://youtu.be/VIq8-6Egtqs
|
||||
|
||||
## Are there YouTube videos on MakeCode for EV3?
|
||||
|
||||
The MakeCode has a [FLL / City Shaper YouTube Channel](https://www.youtube.com/watch?v=IqL0Pyeu5Ng&list=PLMMBk9hE-SeqkOObethhlZtBTEK6FYx3n) with useful videos.
|
||||
|
||||
https://youtu.be/-AirqwC9DL4
|
||||
|
||||
## Do you have examples of program used in competitions?
|
||||
|
||||
The MakeCode team ran a team with friends and family in South Seattle and scored 175 points.
|
||||
The programs used for the crane, swing, red blocks and ramp are at https://github.com/lego-marshmallows (the robot build is not detailled).
|
||||
|
||||
### Why can't I delete my program (*.uf2) files from the Brick?
|
||||
|
||||
There's a bug in the firmware which prevents you from deleting the programs (``*.uf2`` files) from your EV3 Brick. There isn't a firmware update to fix this yet.
|
||||
|
||||
We have prepared a special program that lets you delete UF2 files from the brick.
|
||||
Download [these PDF instructions](/file-manager.pdf) and drop the PDF on the brick drive.
|
||||
This will present you with an menu for deleting files.
|
||||
|
||||
For other common questions, try the FAQ page https://makecode.mindstorms.com/faq.
|
||||
|
||||
## Workarounds
|
||||
|
||||
1. Deleting Programs from the EV3 brick
|
||||
|
||||
>* Description: Unable to delete program files from the EV3 brick after downloading them
|
||||
>* Status: LEGO Education team is working on a fix, no estimated date yet
|
@ -1,36 +0,0 @@
|
||||
# Getting Started
|
||||
|
||||
## Projects
|
||||
|
||||
```codecard
|
||||
[
|
||||
{
|
||||
"name": "Prepare",
|
||||
"imageUrl": "/static/lessons/firmware.png",
|
||||
"description": "To use Microsoft MakeCode with your EV3 Brick, you will need to install the latest LEGO® MINDSTORMS® Education EV3 firmware.",
|
||||
"label": "New? Start Here!",
|
||||
"labelClass": "red ribbon large",
|
||||
"url": "https://makecode.mindstorms.com/troubleshoot"
|
||||
},
|
||||
{
|
||||
"name": "Try",
|
||||
"imageUrl": "/static/lessons/try.png",
|
||||
"description": "Get a quick introduction to programming.",
|
||||
"url": "/getting-started/try",
|
||||
"cardType": "side"
|
||||
},
|
||||
{
|
||||
"name": "Use",
|
||||
"imageUrl": "/static/lessons/use.png",
|
||||
"description": "Build a robot and drive into the world of robotics!",
|
||||
"url": "/getting-started/use",
|
||||
"cardType": "side"
|
||||
},
|
||||
{
|
||||
"name": "First LEGO League",
|
||||
"imageUrl": "/static/fll/fll-big.png",
|
||||
"description": "Information about using MakeCode in FLL competitions",
|
||||
"url": "/fll"
|
||||
}
|
||||
]
|
||||
```
|
@ -1,200 +0,0 @@
|
||||
# Try
|
||||
|
||||
## Introduction @unplugged
|
||||
|
||||
Get a quick introduction to programming with EV3.
|
||||
|
||||
![Display on EV3 Brick with Music Notes](/static/getting-started/01_EyesOn_Intro.png)
|
||||
|
||||
We are excited to help you get started with @boardname@. In this project we will guide you through connecting your EV3 Brick, creating your first program, controlling a Large Motor, a Touch Sensor and a Color Sensor. These steps can take up to 45 minutes.
|
||||
|
||||
## Turn on your EV3 Brick @unplugged
|
||||
|
||||
Power on your EV3 Brick by pressing the Center Button.
|
||||
|
||||
![Hand pressing power button](/static/getting-started/02_PowerOn.png)
|
||||
|
||||
## Connect Your EV3 Brick to Your Device @unplugged
|
||||
|
||||
Use the USB cable to connect your EV3 Brick to your device.
|
||||
|
||||
![Computer and cable connected to EV3 Brick](/static/getting-started/03_insert-usb-02.png)
|
||||
|
||||
## Handle a button press @fullscreen
|
||||
|
||||
Drag out a ``||brick:on button||`` block from Buttons section in the ``||brick:Brick||`` Toolbox drawer.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
})
|
||||
```
|
||||
|
||||
## Change of mood @fullscreen
|
||||
|
||||
Drag a Brick Screen ``||brick:show mood||`` block inside the ``||brick:on button||`` block.
|
||||
Change mood to ``neutral``.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
brick.showMood(moods.neutral)
|
||||
})
|
||||
```
|
||||
|
||||
## Simulate @fullscreen
|
||||
|
||||
**Try out your code in the simulator!**
|
||||
|
||||
Click the center button on the EV3 Brick in the web page. It should display the mood you selected on the screen. Don't hesitate to use the simulator to try out your code during this tutorial!
|
||||
|
||||
![EV3 Brick simulator](/static/getting-started/simulate.png)
|
||||
|
||||
## Play some tunes @fullscreen
|
||||
|
||||
Drag a Music ``||music:play sound effect||`` block below the ``||brick:show mood||`` block.
|
||||
Change sound effect to ``communication hello``.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
brick.showMood(moods.neutral)
|
||||
music.playSoundEffect(sounds.communicationHello)
|
||||
})
|
||||
```
|
||||
|
||||
## Download to your brick @unplugged
|
||||
|
||||
**Download:** Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
### Did It Work?
|
||||
|
||||
Verify that the program you just created shows eyes on the Brick Display, and that the EV3 Brick played the sound “Hello!”
|
||||
|
||||
![EV3 Brick with eyes on the display](/static/getting-started/05_EyesOn.png)
|
||||
|
||||
|
||||
**Well done!**
|
||||
|
||||
## Run it Again
|
||||
|
||||
![EV3 Brick with Try in BrkProg_Save Folder in File Manager](/static/getting-started/try-in-file-manager.png)
|
||||
|
||||
Use the Brick Buttons and navigate to the File Manager tab. Open the **BrkProg_SAVE** folder, select **Try** and click the center button to run it again.
|
||||
|
||||
## Connect a Large Motor @unplugged
|
||||
|
||||
Now you will learn to control the Large Motor.
|
||||
|
||||
![EV3 Brick with hands connecting Large Motor to Port D](/static/getting-started/06_PlugInLargeMotor.png)
|
||||
|
||||
Connect a Large Motor to **Port D** of your EV3 Brick using any of the connector cables.
|
||||
|
||||
## Run a motor @fullscreen
|
||||
|
||||
Drag a ``||motors:run large A motor||`` block inside the ``||brick:on button||`` block.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
motors.largeA.run(50)
|
||||
})
|
||||
```
|
||||
|
||||
## Tune your motor @fullscreen
|
||||
|
||||
Change ``large motor A`` to ``large motor D``.
|
||||
Click on the **(+)** sign and change to ``1`` rotation.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
motors.largeD.run(50, 1, MoveUnit.Rotations)
|
||||
})
|
||||
```
|
||||
|
||||
## Download @unplugged
|
||||
|
||||
**Download:** Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
### Did It Rotate?
|
||||
|
||||
Confirm that your motor has turned one rotation at power level 50 before stopping.
|
||||
|
||||
Download and run the program as many times as you want in order to verify this, or tinker with different power levels and different rotations.
|
||||
|
||||
![Large Motor D w/Rotating “WHRRR,” Hand, EV3 Brick](/static/getting-started/08_WorkingLargeMotor.png)
|
||||
|
||||
## Connect a Touch Sensor @unplugged
|
||||
|
||||
We will now control the Large Motor using a Touch Sensor.
|
||||
|
||||
Keeping the Large Motor connected to **Port D**, connect a Touch Sensor to **Port 1** of your EV3 Brick.
|
||||
|
||||
![Hands connecting Touch Sensor to Port 1 on EV3 Brick](/static/getting-started/09_Connect_Touch.png)
|
||||
|
||||
## Modify Your Program @fullscreen
|
||||
|
||||
* Add a ``||sensors:pause until touch 1 pressed||`` Sensor block on top of the ``||motors:run large motor D||`` block.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
sensors.touch1.pauseUntil(ButtonEvent.Pressed)
|
||||
motors.largeD.run(50, 1, MoveUnit.Rotations)
|
||||
})
|
||||
```
|
||||
|
||||
## Download @unplugged
|
||||
|
||||
**Download:** Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
### Press the Touch Sensor
|
||||
|
||||
Confirm that the Large Motor has turned one rotation AFTER you press the Touch Sensor.
|
||||
|
||||
Download and run the program as many times as you want in order to verify this, or tinker with different Touch Sensor and Large Motor values.
|
||||
|
||||
![Hand Touch Sensor Pressed & EV3 Brick & Large Motor](/static/getting-started/11_TouchMotorWorking.png)
|
||||
|
||||
## Connect a Color Sensor @unplugged
|
||||
|
||||
Now we will try to control the Large Motor using another sensor.
|
||||
|
||||
![Hand connecting Color Sensor to Port 4, Large Motor D, EV3 Brick](/static/getting-started/12_ConnectColor.png)
|
||||
|
||||
Keeping the Large Motor connected to **Port D**, connect the Color Sensor to **Port 4**.
|
||||
|
||||
## Update your code @fullscreen
|
||||
|
||||
Using the same program, replace the ``||sensors:pause until touch 1||`` block with a ``||sensors:pause color sensor 3||`` for color block.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Green)
|
||||
motors.largeD.run(50, 1, MoveUnit.Rotations)
|
||||
})
|
||||
```
|
||||
|
||||
Don't forget to select the color you want to detect (e.g., green)!
|
||||
|
||||
## Download @unplugged
|
||||
|
||||
**Download:** Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
### Place a Colored Brick in Front of the Color Sensor
|
||||
|
||||
Confirm that the Large Motor has turned one rotation AFTER the Color Sensor has detected the colored brick.
|
||||
|
||||
Download and run the program as many times as you want in order to verify this, or tinker with different Color Sensor and Large Motor values.
|
||||
|
||||
![IMG: Colored bricks in front of Color Sensor, hands, EV3 Brick](/static/getting-started/14_ColorSensorWorking.png)
|
||||
|
||||
## JavaScript @fullscreen
|
||||
|
||||
Click on the **JavaScript** tab and change the color the Color Sensor detects to Black, Blue, Green, Yellow, Red, White, or Brown. Use Title Case for the color names.
|
||||
|
||||
```typescript
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Blue)
|
||||
motors.largeD.run(50, 1, MoveUnit.Rotations)
|
||||
})
|
||||
```
|
||||
|
||||
## Well Done! @unplugged
|
||||
|
||||
You have now learned how to control some of the inputs and outputs of the EV3.
|
@ -1,171 +0,0 @@
|
||||
# Try
|
||||
|
||||
Get a quick introduction to programming with EV3.
|
||||
|
||||
![Display on EV3 Brick with Music Notes](/static/getting-started/01_EyesOn_Intro.png)
|
||||
|
||||
We are excited to help you get started with @boardname@. In this project we will guide you through connecting your EV3 Brick, creating your first program, controlling a Large Motor, a Touch Sensor and a Color Sensor. These steps can take up to 45 minutes.
|
||||
|
||||
## Turn on your EV3 Brick
|
||||
|
||||
Power on your EV3 Brick by pressing the Center Button.
|
||||
|
||||
![Hand pressing power button](/static/getting-started/02_PowerOn.png)
|
||||
|
||||
## Connect Your EV3 Brick to Your Device
|
||||
|
||||
Use the USB cable to connect your EV3 Brick to your device.
|
||||
|
||||
![Computer and cable connected to EV3 Brick](/static/getting-started/03_insert-usb-02.png)
|
||||
|
||||
## Create and Run your First Program
|
||||
|
||||
**Code it:** Create the program shown here.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
brick.showMood(moods.neutral)
|
||||
music.playSoundEffect(sounds.communicationHello)
|
||||
})
|
||||
```
|
||||
|
||||
* Drag out a ``||brick:on button||`` block from Buttons section in the ``||brick:Brick||`` Toolbox drawer.
|
||||
* Drag a Brick Screen ``||brick:show mood||`` block inside the ``||brick:on button||`` block.
|
||||
* Change mood to ``neutral``.
|
||||
|
||||
```block
|
||||
brick.showMood(moods.neutral)
|
||||
```
|
||||
|
||||
* Drag a Music ``||music:play sound effect||`` block below the ``||brick:show mood||`` block.
|
||||
* Change sound effect to ``communication hello``.
|
||||
|
||||
```block
|
||||
music.playSoundEffect(sounds.communicationHello)
|
||||
```
|
||||
|
||||
**Download:** Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
## Did It Work?
|
||||
|
||||
![EV3 Brick with eyes on the display](/static/getting-started/05_EyesOn.png)
|
||||
|
||||
Verify that the program you just created shows eyes on the Brick Display, and that the EV3 Brick played the sound “Hello!”
|
||||
|
||||
**Well done!**
|
||||
|
||||
## Run it Again
|
||||
|
||||
![EV3 Brick with Try in BrkProg_Save Folder in File Manager](/static/getting-started/try-in-file-manager.png)
|
||||
|
||||
Use the Brick Buttons and navigate to the File Manager tab. Open the **BrkProg_SAVE** folder, select **Try** and click the center button to run it again.
|
||||
|
||||
## Connect a Large Motor
|
||||
|
||||
Now you will learn to control the Large Motor.
|
||||
|
||||
![EV3 Brick with hands connecting Large Motor to Port D](/static/getting-started/06_PlugInLargeMotor.png)
|
||||
|
||||
Connect a Large Motor to **Port D** of your EV3 Brick using any of the connector cables.
|
||||
|
||||
## Create and Run This Program
|
||||
|
||||
**Code it:** Create the program shown here.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
motors.largeD.run(50, 1, MoveUnit.Rotations)
|
||||
})
|
||||
```
|
||||
|
||||
* Start a new program.
|
||||
* Drag a ``||motors:run large A motor||`` block inside the ``||brick:on button||`` block.
|
||||
* Change ``large motor A`` to ``large motor D``.
|
||||
* Click on the **(+)** sign.
|
||||
* Change to ``1`` rotation.
|
||||
|
||||
**Download:** Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
## Did It Rotate?
|
||||
|
||||
Confirm that your motor has turned one rotation at power level 50 before stopping.
|
||||
|
||||
![Large Motor D w/Rotating “WHRRR,” Hand, EV3 Brick](/static/getting-started/08_WorkingLargeMotor.png)
|
||||
|
||||
Download and run the program as many times as you want in order to verify this, or tinker with different power levels and different rotations.
|
||||
|
||||
## Connect a Touch Sensor
|
||||
|
||||
We will now control the Large Motor using a Touch Sensor.
|
||||
|
||||
![Hands connecting Touch Sensor to Port 1 on EV3 Brick](/static/getting-started/09_Connect_Touch.png)
|
||||
|
||||
Keeping the Large Motor connected to **Port D**, connect a Touch Sensor to **Port 1** of your EV3 Brick.
|
||||
|
||||
## Modify Your Program
|
||||
|
||||
**Code it:** Add code to the program for the Touch Sensor.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
sensors.touch1.pauseUntil(ButtonEvent.Pressed)
|
||||
motors.largeD.run(50, 1, MoveUnit.Rotations)
|
||||
})
|
||||
```
|
||||
|
||||
* Add a ``||sensors:pause until touch 1 pressed||`` Sensor block on top of the ``||motors:run large motor D||`` block.
|
||||
|
||||
```block
|
||||
sensors.touch1.pauseUntil(ButtonEvent.Pressed)
|
||||
```
|
||||
|
||||
**Download:** Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
## Press the Touch Sensor
|
||||
|
||||
Confirm that the Large Motor has turned one rotation AFTER you press the Touch Sensor.
|
||||
|
||||
![Hand Touch Sensor Pressed & EV3 Brick & Large Motor](/static/getting-started/11_TouchMotorWorking.png)
|
||||
|
||||
Download and run the program as many times as you want in order to verify this, or tinker with different Touch Sensor and Large Motor values.
|
||||
|
||||
## Connect a Color Sensor
|
||||
|
||||
Now we will try to control the Large Motor using another sensor.
|
||||
|
||||
![Hand connecting Color Sensor to Port 4, Large Motor D, EV3 Brick](/static/getting-started/12_ConnectColor.png)
|
||||
|
||||
Keeping the Large Motor connected to **Port D**, connect the Color Sensor to **Port 4**.
|
||||
|
||||
**Code it:** Modify Your Program to use the Color Sensor.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
sensors.color4.pauseUntilColorDetected(ColorSensorColor.Green)
|
||||
motors.largeD.run(50, 1, MoveUnit.Rotations)
|
||||
})
|
||||
```
|
||||
|
||||
* Using the same program, replace the ``||sensors:pause until touch 1||`` block with a ``||sensors:pause color sensor 4||`` for color block.
|
||||
|
||||
```block
|
||||
sensors.color4.pauseUntilColorDetected(ColorSensorColor.Green)
|
||||
```
|
||||
|
||||
* Select the color you want to detect (e.g., green).
|
||||
|
||||
**Download:** Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
## Place a Colored Brick in Front of the Color Sensor
|
||||
|
||||
![IMG: Colored bricks in front of Color Sensor, hands, EV3 Brick](/static/getting-started/14_ColorSensorWorking.png)
|
||||
|
||||
Confirm that the Large Motor has turned one rotation AFTER the Color Sensor has detected the colored brick.
|
||||
|
||||
Download and run the program as many times as you want in order to verify this, or tinker with different Color Sensor and Large Motor values.
|
||||
|
||||
Click on the **JavaScript** tab and change the color the Color Sensor detects to Black, Blue, Green, Yellow, Red, White, or Brown. Use Title Case for the color names.
|
||||
|
||||
## Well Done!
|
||||
|
||||
You have now learned how to control some of the inputs and outputs of the EV3.
|
@ -1,121 +0,0 @@
|
||||
# Use
|
||||
|
||||
Build a robot and drive into the world of robotics!
|
||||
|
||||
![EV3 Driving Base full w/cuboid](/static/getting-started/EV3_GettingStarted_13.jpg)
|
||||
|
||||
In this project we will guide you through building a Driving Base Robot and programming it to move straight and turn. You will also build and Object Detector Module, and program it to detect an object. It’s a good idea to have done the [Try](/getting-started/try) sequence first.
|
||||
|
||||
## Connect
|
||||
|
||||
What if your school had a multipurpose robot? How would you use it?
|
||||
|
||||
![Apple Picker Robot](/static/getting-started/02_ApplePickerRobot.jpg)
|
||||
|
||||
Would you use it to clean the school or plant trees?
|
||||
|
||||
## Build Your Driving Base Robot
|
||||
|
||||
Build the robot driving base:
|
||||
|
||||
[![EV3 Driving Base](/static/lessons/common/ev3-driving-base.jpg)](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-rem-driving-base-79bebfc16bd491186ea9c9069842155e.pdf)
|
||||
|
||||
### ~hint
|
||||
|
||||
If clicking the above image doesn't open the instructions, right-click on the image and choose "Save link as..." to download the PDF.
|
||||
|
||||
### ~
|
||||
|
||||
## Make It Move
|
||||
|
||||
**Code it:** Create a program that makes the Driving Base move forward and stop at the finish line, which is ``1`` meter away.
|
||||
|
||||
Start by building this program:
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
motors.largeBC.steer(0, 50, 1, MoveUnit.Rotations)
|
||||
})
|
||||
```
|
||||
|
||||
* Drag a ``||motors:steer large motors B+C||`` block inside an ``||brick:on button||`` block.
|
||||
* Click on the **(+)** sign.
|
||||
* Change to ``1`` rotation.
|
||||
|
||||
### ~hint
|
||||
|
||||
**Hint:** You will have to modify the number of rotations until you find the number that matches the robot moving forward 1 meter and stopping.
|
||||
|
||||
### ~
|
||||
|
||||
**Download:** Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
## Make It Turn
|
||||
|
||||
**Code it:** Create a new program that turns the Driving Base 180 degrees.
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
motors.largeBC.steer(-50, 50, 1, MoveUnit.Rotations)
|
||||
})
|
||||
```
|
||||
|
||||
### ~hint
|
||||
|
||||
**Hint:** You will have to modify the turn ratio and the number of rotations until the robot reaches 180 degrees.
|
||||
|
||||
### ~
|
||||
|
||||
**Download:** Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
## Add an Ultrasonic Sensor to Your Driving Base
|
||||
|
||||
Build and attach an Ultrasonic Sensor to your driving base:
|
||||
|
||||
[![EV3 Ultrasonic Sensor Driving Base Building Instructions Main Image](/static/lessons/common/ev3-ultrasonic-sensor-driving-base.jpg)](https://le-www-live-s.legocdn.com/sc/media/lessons/mindstorms-ev3/building-instructions/ev3-ultrasonic-sensor-driving-base-61ffdfa461aee2470b8ddbeab16e2070.pdf)
|
||||
|
||||
### ~hint
|
||||
|
||||
If clicking the above image doesn't open the instructions, right-click on the image and choose "Save link as..." to download the PDF.
|
||||
|
||||
### ~
|
||||
|
||||
## Detect an Object
|
||||
|
||||
**Code it:** Create a program that moves the Driving Base and makes it stop ``6`` cm from the Cuboid.
|
||||
|
||||
Create a new program:
|
||||
|
||||
```blocks
|
||||
brick.buttonEnter.onEvent(ButtonEvent.Pressed, function () {
|
||||
motors.largeBC.tank(50, 50)
|
||||
sensors.ultrasonic4.setThreshold(UltrasonicSensorEvent.ObjectDetected, 6)
|
||||
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectDetected);
|
||||
motors.stopAll()
|
||||
})
|
||||
```
|
||||
|
||||
* Drag a ``||motors:tank large motors B+C||`` motor block inside the ``||brick:on button||`` block.
|
||||
* Drag the Ultrasonic Sensor threshold ``||sensors:set ultrasonic 4||`` block and place it below the motor block.
|
||||
* Drag a ``|sensors:pause until ultrasonic 4||`` block and place it under the threshold block.
|
||||
* Drag a ``||motors:stop all motors||`` block and place it below the sensor block.
|
||||
|
||||
### ~hint
|
||||
|
||||
**Hint:** You will have to modify the values of the Ultrasonic Sensor block until the robot reaches the desired position.
|
||||
|
||||
### ~
|
||||
|
||||
**Download:** Click **Download** and follow the instructions to get your code onto your EV3 Brick. Press the center button on the EV3 Brick to run the program.
|
||||
|
||||
Click on the **JavaScript** tab. Change and test the number value of the Ultrasonic
|
||||
Sensor.
|
||||
|
||||
```typescript
|
||||
sensors.ultrasonic4.setThreshold(UltrasonicSensorEvent.ObjectDetected, 10)
|
||||
```
|
||||
|
||||
**Congratulations!**
|
||||
|
||||
You are ready to move on to the next steps.
|
||||
Try a [Design Engineering](/design-engineering), [Coding](/coding), or [Maker](/maker) activity.
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"appref": "v1.2.31"
|
||||
"appref": "v"
|
||||
}
|
||||
|
254
docs/labview.md
254
docs/labview.md
@ -1,254 +0,0 @@
|
||||
# Coding in MakeCode
|
||||
|
||||
This guide helps users who are used to working with @boardname@ become familiar with using blocks in MakeCode.
|
||||
|
||||
## Snap together the blocks
|
||||
|
||||
Just like in LabView, blocks in the MakeCode editor can be dragged from the cabinet and snapped together
|
||||
to create a sequence of program instructions.
|
||||
|
||||
Take a look a the LabView program below: it **starts**, turns on motor A, waits a second, and finally stops motor A.
|
||||
|
||||
![sequence of block](/static/labview/sequencing.png)
|
||||
|
||||
The blocks in MakeCode have similar functions and go together in the same way: they snap into the ``||loops:on start||`` block and then connect to each other vertically.
|
||||
|
||||
```blocks
|
||||
motors.largeA.run(50)
|
||||
pause(1000)
|
||||
motors.largeA.stop()
|
||||
```
|
||||
|
||||
Any block program can be converted to JavaScript and you can edit it as lines of code too.
|
||||
|
||||
```typescript
|
||||
motors.largeA.run(50)
|
||||
pause(1000)
|
||||
motors.largeA.stop()
|
||||
```
|
||||
|
||||
## Download to the EV3
|
||||
|
||||
Before you actually run your program on the EV3 Brick, you can first try it in the simulator. The MakeCode editor includes a simulator in the browser for you to test your code. You can make changes to your program and check them out it the simulator to make sure your code works the way want. The similator knows when you modify your code and it restarts automatically to run the new code.
|
||||
|
||||
Once you're ready to transfer your program to the EV3 Brick, click the ``|Download|`` button and follow the instructions.
|
||||
|
||||
## Single motors
|
||||
|
||||
This program controls a large motor on port A in several different ways. It sets just the speed and then sets speed for: an amount of time, angle of movement, and a number of rotations.
|
||||
|
||||
![Single motor blocks](/static/labview/motors.png)
|
||||
|
||||
```blocks
|
||||
motors.largeA.run(50);
|
||||
motors.largeA.run(50, 1000, MoveUnit.MilliSeconds);
|
||||
motors.largeA.run(50, 360, MoveUnit.Degrees);
|
||||
motors.largeA.run(50, 1, MoveUnit.Rotations);
|
||||
motors.largeA.stop();
|
||||
```
|
||||
|
||||
## Steering
|
||||
|
||||
The **steering** blocks let you to synchronize two motors at a precise rate. They can also specify the duration, angle, or number of rotations for the motors to turn.
|
||||
|
||||
![Steering blocks](/static/labview/steer.png)
|
||||
|
||||
```blocks
|
||||
motors.largeBC.steer(0, 50);
|
||||
motors.largeBC.steer(0, 50, 1000, MoveUnit.MilliSeconds);
|
||||
motors.largeBC.steer(0, 50, 360, MoveUnit.Degrees);
|
||||
motors.largeBC.steer(0, 50, 1, MoveUnit.Rotations);
|
||||
motors.largeBC.stop();
|
||||
```
|
||||
|
||||
### ~ hint
|
||||
|
||||
The **turn ratio range is -200, 200** unlike LabView who used -100,100.
|
||||
|
||||
### ~
|
||||
|
||||
## Tank
|
||||
|
||||
The **tank** blocks control the speed of two motors. These are commonly used for a differential drive robot. The blocks can also specify the duration, angle, or number of rotations.
|
||||
|
||||
![Tank block](/static/labview/tank.png)
|
||||
|
||||
```blocks
|
||||
motors.largeBC.tank(50, 50);
|
||||
motors.largeBC.tank(50, 50, 1000, MoveUnit.MilliSeconds);
|
||||
motors.largeBC.tank(50, 50, 360, MoveUnit.Degrees);
|
||||
motors.largeBC.tank(50, 50, 1, MoveUnit.Rotations);
|
||||
motors.largeBC.stop();
|
||||
```
|
||||
|
||||
## Coasting and braking
|
||||
|
||||
By default, all motors coast when any command used to move finishes. You can keep them from coasting with the ``||motors:set brake||`` block.
|
||||
|
||||
![Brake block](/static/labview/brake.png)
|
||||
|
||||
```blocks
|
||||
motors.largeD.setBrake(true);
|
||||
motors.largeD.run(50, 1, MoveUnit.Rotations)
|
||||
```
|
||||
|
||||
## Inverting and regulating motors
|
||||
|
||||
If you wan to change the direction that a motor turns, use the ``||motors:set inverted||`` block.
|
||||
|
||||
![Brake block](/static/labview/invertmotor.png)
|
||||
|
||||
```blocks
|
||||
motors.largeA.setInverted(true);
|
||||
```
|
||||
|
||||
By default, the speed of motors is regulated. This means that if your robot goes up a hill,
|
||||
the regulator will adjust the power to match the desired speed. You can disable this feature
|
||||
using ``||motors:set regulated||``.
|
||||
|
||||
![Brake block](/static/labview/unregulatedmotor.png)
|
||||
|
||||
```blocks
|
||||
motors.largeA.setRegulated(false);
|
||||
```
|
||||
|
||||
## Brick
|
||||
|
||||
The **Brick** category has a number of blocks to display graphics on the brick screen.
|
||||
|
||||
![brick image](/static/labview/brickimage.png)
|
||||
|
||||
```blocks
|
||||
brick.clearScreen()
|
||||
brick.showImage(images.expressionsWink)
|
||||
```
|
||||
|
||||
![brick status light](/static/labview/brickstatuslight.png)
|
||||
|
||||
```blocks
|
||||
brick.setStatusLight(StatusLight.Off);
|
||||
brick.setStatusLight(StatusLight.Red);
|
||||
brick.setStatusLight(StatusLight.OrangePulse);
|
||||
```
|
||||
|
||||
## Waiting (pausing)
|
||||
|
||||
It is quite common to have to wait for a task to finish or for a sensor state to change, such as when a touch button pressed. The ``||loops:pause||`` and ``||sensors:pause until||`` blocks provide a way for your program to wait for a period of time.
|
||||
|
||||
![pause for time](/static/labview/pausefortime.png)
|
||||
|
||||
```blocks
|
||||
motors.largeD.run(50)
|
||||
pause(1000)
|
||||
motors.largeD.stop();
|
||||
```
|
||||
|
||||
![pause for touch](/static/labview/pausefortouch.png)
|
||||
|
||||
```blocks
|
||||
motors.largeD.run(50)
|
||||
sensors.touch1.pauseUntil(ButtonEvent.Pressed)
|
||||
motors.largeD.stop();
|
||||
```
|
||||
|
||||
![pause for distance](/static/labview/pausefordistance.png)
|
||||
|
||||
```blocks
|
||||
motors.largeD.run(50)
|
||||
sensors.ultrasonic4.pauseUntil(UltrasonicSensorEvent.ObjectNear)
|
||||
motors.largeD.stop();
|
||||
```
|
||||
|
||||
You can also use the ``||loops:pause until||`` block to wait on any [boolean](/types/boolean) expression. As your program runs, it waits until the condition (expression) inside becomes true.
|
||||
|
||||
```blocks
|
||||
motors.largeD.run(50)
|
||||
pauseUntil(() => sensors.touch1.isPressed())
|
||||
motors.largeD.stop()
|
||||
```
|
||||
|
||||
## Loops
|
||||
|
||||
![Single loop](/static/labview/loopinfinite.png)
|
||||
|
||||
```blocks
|
||||
forever(() => {
|
||||
motors.largeD.run(50, 1, MoveUnit.Rotations);
|
||||
motors.largeD.run(-50, 1, MoveUnit.Rotations);
|
||||
})
|
||||
```
|
||||
|
||||
![While loop](/static/labview/while.png)
|
||||
|
||||
```blocks
|
||||
for(let i = 0; i < 10; i++) {
|
||||
motors.largeD.run(50, 1, MoveUnit.Rotations);
|
||||
motors.largeD.run(-50, 1, MoveUnit.Rotations);
|
||||
}
|
||||
let k = 0;
|
||||
while(k < 10) {
|
||||
motors.largeD.run(50, 1, MoveUnit.Rotations);
|
||||
motors.largeD.run(-50, 1, MoveUnit.Rotations);
|
||||
k++;
|
||||
}
|
||||
```
|
||||
|
||||
## Variables
|
||||
|
||||
![Variable block](/static/labview/speedoflightvar.png)
|
||||
|
||||
```blocks
|
||||
let light = 0;
|
||||
forever(function () {
|
||||
light = sensors.color3.light(LightIntensityMode.Reflected);
|
||||
motors.largeD.run(light)
|
||||
})
|
||||
```
|
||||
|
||||
## Concurrent loops
|
||||
|
||||
You can start up multiple ``||loops:forever||`` loops that run at the same time. Actually, only the code in just one of the loops is really running at any exact moment in time. Each loop, though, gets a turn to run all of its code and this makes them run [_concurrently_](https://en.wikipedia.org/wiki/Concurrent_computing).
|
||||
|
||||
![Multiple loops running at the same time](/static/labview/multipleloops.png)
|
||||
|
||||
```blocks
|
||||
forever(() => {
|
||||
motors.largeD.run(50, 1, MoveUnit.Rotations);
|
||||
motors.largeD.run(-50, 1, MoveUnit.Rotations);
|
||||
})
|
||||
forever(() => {
|
||||
brick.showImage(images.eyesMiddleRight)
|
||||
pause(1000)
|
||||
brick.showImage(images.eyesMiddleLeft)
|
||||
pause(1000)
|
||||
})
|
||||
```
|
||||
|
||||
## Conditional
|
||||
|
||||
The ``||logic:if||`` block allows you to run different code depending on whether some condition ([boolean](/types/boolean) expression) is `true` or `false`. Also, this is similar to the ``||loops:switch||`` block.
|
||||
|
||||
![Brake block](/static/labview/ife.png)
|
||||
|
||||
```blocks
|
||||
forever(function() {
|
||||
if(sensors.touch1.isPressed()) {
|
||||
motors.largeD.run(50)
|
||||
} else {
|
||||
motors.largeD.stop()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Random
|
||||
|
||||
The ``||math:pick random||`` block returns a random number selected from a range of numbers.
|
||||
|
||||
![Brake block](/static/labview/random.png)
|
||||
|
||||
```blocks
|
||||
forever(function () {
|
||||
motors.largeBC.steer(Math.randomRange(-5, 5), 50)
|
||||
pause(100)
|
||||
})
|
||||
```
|
@ -1,27 +0,0 @@
|
||||
# Lessons
|
||||
|
||||
Learning activities for @boardname@ with MakeCode.
|
||||
|
||||
## Motors and motion
|
||||
|
||||
```codecard
|
||||
[{
|
||||
"name": "Make it Move",
|
||||
"imageUrl":"/static/lessons/make-it-move.jpg",
|
||||
"url": "/lessons/make-it-move",
|
||||
"cardType": "project",
|
||||
"description": "Make a robot that moves itself without wheels."
|
||||
}, {
|
||||
"name": "Make it Move TUTORIAL",
|
||||
"imageUrl":"/static/lessons/make-it-move.jpg",
|
||||
"url": "/lessons/make-it-move-tutorial",
|
||||
"cardType": "tutorial",
|
||||
"description": "Make a robot that moves itself without wheels."
|
||||
}, {
|
||||
"name": "Line Detection",
|
||||
"imageUrl":"/static/lessons/line-detection.jpg",
|
||||
"url": "/lessons/line-detection",
|
||||
"cardType": "project",
|
||||
"description": "Make your robot drive itself by following lines."
|
||||
}]
|
||||
```
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user