Compare commits

...

77 Commits

Author SHA1 Message Date
4e99cd3ef1 0.0.26 2017-10-27 19:23:01 +01:00
57647318c4 Sensor fixes 2017-10-27 19:18:56 +01:00
2720698864 Fix infinite loop 2017-10-27 19:18:47 +01:00
c0bab4877a Merge branch 'master' of github.com:Microsoft/pxt-ev3 2017-10-27 15:17:24 +01:00
d2a1d10ada Add converter from RGF to PNG 2017-10-27 15:17:21 +01:00
bcb68d937d Merge branch 'master' of https://github.com/microsoft/pxt-ev3 2017-10-27 02:52:47 -07:00
05a8395028 stop all motors 2017-10-27 02:52:42 -07:00
3a1601a419 Add rsf2wav.js 2017-10-27 10:42:33 +01:00
712c2178d2 simplify motor API 2017-10-27 01:47:25 -07:00
12cdad72c8 added puppet 2017-10-27 00:13:51 -07:00
95076f8f24 differentiate large/medium motors 2017-10-27 00:09:00 -07:00
6391620373 added 2 more activities 2017-10-26 23:58:34 -07:00
86212e2153 added sound of color 2017-10-26 23:46:55 -07:00
98e430f3c1 added example of converted lesson 2017-10-26 22:19:16 -07:00
5c7e856e7b removed incorrect buy link 2017-10-26 21:57:48 -07:00
a47988913e 0.0.25 2017-10-26 21:27:51 -07:00
ea72dba6c7 Merge pull request #17 from Microsoft/irevents
Ultrasonic + IR events + Remote events
2017-10-27 06:25:02 +02:00
215e846a54 refactored remote button 2017-10-26 21:10:37 -07:00
21b34cb459 simplified events 2017-10-26 20:57:18 -07:00
282134f5dc refactoring IR 2017-10-26 20:51:13 -07:00
6b44352839 event for ultrasonic module 2017-10-26 20:38:17 -07:00
9a883d5672 Merge branch 'master' into irevents 2017-10-26 20:21:06 -07:00
59ce4338d3 renaming IR events 2017-10-26 20:20:24 -07:00
90560050b8 Merge pull request #16 from Microsoft/fonts
Mounting events on various sensors
2017-10-27 05:19:36 +02:00
2c72173bfe Use the _query() infrastructure for polling 2017-10-25 13:34:05 +02:00
1a5992408b added event for color changes 2017-10-24 23:10:27 -07:00
0e1a3b7e6b adding setpixel 2017-10-24 22:05:24 -07:00
ea6bfa03bd touched -> pressed 2017-10-24 21:55:37 -07:00
20d584db2b 0.0.24 2017-10-24 21:18:16 -07:00
0e4e0d8899 0.0.23 2017-10-24 21:09:56 -07:00
a18a690417 Merge pull request #12 from Microsoft/motors
Converting motors to fixed instances
2017-10-25 06:09:27 +02:00
c9d57c5e8d enabling banner 2017-10-24 21:08:02 -07:00
7e9d42a571 reset motors on start 2017-10-24 20:28:31 -07:00
1b51320edb pausing while running motor 2017-10-24 20:20:07 -07:00
4f44238237 use fixed instances for motors 2017-10-24 20:16:33 -07:00
c8ffa0ded7 fixed test 2017-10-24 18:49:15 -07:00
6b07d5f716 0.0.22 2017-10-24 18:48:30 -07:00
8784e23b60 fixed build link 2017-10-24 17:01:36 -07:00
4b8409fbc0 0.0.21 2017-10-24 16:56:52 -07:00
3237978cba Merge pull request #4 from Microsoft/blockupdate
Blocks update
2017-10-24 16:56:32 -07:00
33c8902050 aligning groups with hardware name components 2017-10-24 16:52:13 -07:00
fa6c81cf80 buttons -> brick buttons 2017-10-24 16:25:03 -07:00
46175fc7db separating touch sensor stuff 2017-10-24 15:58:47 -07:00
e6ef86101f more renaming 2017-10-24 15:37:48 -07:00
c4d3d7634e fixed naming of sonar 2017-10-24 15:35:42 -07:00
b0380fbef8 more annotations 2017-10-24 15:33:28 -07:00
c85c68ab68 fixing color / gyro 2017-10-24 15:22:07 -07:00
334d5aca9a on/off field editors on motors 2017-10-24 15:03:21 -07:00
1330a0fb82 fixed gyro def 2017-10-24 14:54:36 -07:00
005447ce44 4 times more sensors\! 2017-10-24 19:58:52 +01:00
60d5271de2 Merge branch 'master' into blockupdate 2017-10-24 10:02:27 -07:00
e3ab6ace55 0.0.20 2017-10-24 10:01:49 -07:00
5f4488dea7 Merge pull request #3 from Microsoft/pxtupdate
Updated to latest of pxt / common
2017-10-24 10:00:41 -07:00
07dc3bdae1 fixing docs compilation 2017-10-24 09:55:38 -07:00
5d5d78ced0 compiled strings 2017-10-24 09:47:30 -07:00
fe46461c4c adding a few more blocks 2017-10-24 05:30:05 -07:00
ccda971fd1 Bump PXT and common packages 2017-10-24 12:50:00 +01:00
8fa6cf41ca updated build files 2017-10-23 13:43:59 -07:00
aa3c6d5fc0 bump pxt-core to 2.3.1, bump pxt-common-packages to 0.10.16, 2017-10-23 13:41:38 -07:00
6a719e7718 Use field toggle for switching the motor on / off 2017-10-04 17:04:26 -04:00
b18b8333d0 Remove button group 2017-10-03 02:31:06 -04:00
84d80131d4 Various UI fixes. Block refactoring and adding touch and color blocks. 2017-10-03 02:28:44 -04:00
4977358718 0.0.19 2017-09-15 10:06:47 -07:00
15b2ef6c92 Update theme.config 2017-09-15 10:06:33 -07:00
e0288ed741 bump pxt-core to 2.0.49, bump pxt-common-packages to 0.9.6, 2017-09-15 10:04:01 -07:00
df1caf9741 0.0.18 2017-09-01 16:50:18 -07:00
a755420d06 bump pxt-core to 2.0.34, bump pxt-common-packages to 0.9.3, 2017-09-01 16:50:13 -07:00
a139727fea 0.0.17 2017-08-28 21:52:26 -07:00
48e081e584 Update json strings 2017-08-28 21:52:09 -07:00
124ad5c915 bump pxt-core to 2.0.29, 2017-08-28 21:51:33 -07:00
75a571fda7 Update README.md 2017-08-14 14:35:03 -07:00
bb842056d4 0.0.16 2017-08-10 17:11:02 -07:00
41b023f83f bump pxt-core to 2.0.12, 2017-08-10 17:10:57 -07:00
1ff058460f Split out blockly into blockly.less 2017-08-10 17:10:08 -07:00
cb0895f166 Moving UF2 related code away from this repo 2017-08-10 09:49:30 -07:00
1340fd0162 0.0.15 2017-08-09 10:03:14 -07:00
a3f56f4c9a Fix pattern enum decompilation and setSpeed when no speed is set. 2017-08-09 10:02:58 -07:00
84 changed files with 1484 additions and 13277 deletions

1
.gitignore vendored
View File

@ -31,3 +31,4 @@ videos/**
lib/
.vscode/
bin
scripts/out.*

View File

@ -1,8 +1,8 @@
# LEGO Mindstorms EV3 target for PXT
[![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/)
[![Build Status](https://ci2.dot.net/buildStatus/icon?job=Private/pxt_project_rainbow/master/pxt-ev3_Push)](https://ci2.dot.net/job/Private/job/pxt_project_rainbow/job/master/job/pxt-ev3_Push/)
This repo contains the editor target hosted at https://lego.makecode.com
This repo contains the editor target hosted at https://d541eec2-1e96-4b7b-a223-da9d01d0337a.pxt.io/
## Local Dev setup

View File

@ -1,12 +0,0 @@
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

View File

@ -1,35 +0,0 @@
# 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:
* additional `/sys/.../lun0/active` entry is added, which allows for signaling drive eject to the host
* `d_usbdev` has an additional `ioctl()` to pretend data came from the USB host - this can be used to direct
the VM to do stuff
### 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.

View File

@ -1,10 +0,0 @@
#!/bin/sh
set -ex
echo Y > /sys/module/printk/parameters/time
cd /mnt/ramdisk/prjs/ko
#echo 3 > /proc/sys/kernel/printk
insmod ./nbd.ko
sleep 1
./uf2d /dev/nbd1 > /tmp/uf2d.log 2> /tmp/uf2derr.log
sleep 1
insmod ./d_usbdev.ko file=/dev/nbd1 HostStr=EV3 SerialStr=0016535543af

View File

@ -1,2 +0,0 @@
obj-m += $(MOD).o

File diff suppressed because it is too large Load Diff

View File

@ -1,762 +0,0 @@
/*
* 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 "source/lms2012.h"
#include "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>
static struct fsg_common *fsg_common;
#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>
#include "f_mass_storage.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 = 0xEF,
.bDeviceSubClass = 2,
.bDeviceProtocol = 1,
/*.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 msg_bind(struct usb_composite_dev *cdev);
static void msg_bind2(struct usb_composite_dev *cdev);
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;
id = msg_bind(cdev);
if (id < 0)
return 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);
}
msg_bind2(cdev);
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);
}
#define FEED_DATA _IOC(_IOC_WRITE, 't', 108, 1024)
static int Device1Ioctl(struct inode *pNode, struct file *File, unsigned int Request, unsigned long Pointer)
{
if (Request != FEED_DATA)
return -EINVAL;
copy_from_user(usb_char_buffer_out,(void*)Pointer,1024);
usb_char_out_length = 1024;
return 0;
}
static const struct file_operations Device1Entries =
{
.owner = THIS_MODULE,
.read = Device1Read,
.write = Device1Write,
.mmap = Device1Mmap,
.ioctl = Device1Ioctl
};
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();
}
// MSG
/****************************** Configurations ******************************/
static struct fsg_module_parameters fsg_mod_data = {
.stall = 1
};
FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
/****************************** Gadget Bind ******************************/
static void msg_bind2(struct usb_composite_dev *cdev)
{
fsg_common_put(fsg_common);
}
static int msg_bind(struct usb_composite_dev *cdev)
{
/* set up mass storage function */
fsg_common = fsg_common_from_params(0, cdev, &fsg_mod_data);
if (IS_ERR(fsg_common)) {
return PTR_ERR(fsg_common);
}
return 0;
}
static int msg_config(struct usb_configuration *c) {
return fsg_add(c->cdev, c, fsg_common);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,276 +0,0 @@
/*
* 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 */

View File

@ -1,249 +0,0 @@
/*
* 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_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,81 +0,0 @@
/*
* 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_ */

View File

@ -1,81 +0,0 @@
/*
* 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_ */

View File

@ -1,88 +0,0 @@
/*
* 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_ */

View File

@ -1,76 +0,0 @@
/*
* 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_ */

View File

@ -1,38 +0,0 @@
/*
* 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_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,195 +0,0 @@
/*
* 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_ */

View File

@ -1,56 +0,0 @@
/*
* 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_ */

View File

@ -1,779 +0,0 @@
/*
* 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_DISABLE,
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);
}

View File

@ -1,738 +0,0 @@
/*
* 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 msg_config(struct usb_configuration *c);
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;
}
status = msg_config(c);
if (status) {
kfree(rudolf);
return status;
}
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);
}

View File

@ -1,7 +0,0 @@
#!/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/

View File

@ -1,14 +0,0 @@
# Patched EV3 image
The file `ev3-fs.patch` summarizes the changes done to the original V1.09D image.
You can see some text files are edited, the `d_usbdev.ko` is updated (sources in `../kernel`),
`uf2d` added (sources in `../uf2daemon`), and a stock `nbd.ko` module is added.
Additionally, the `edimax01.ko` is replaced by now much more popular `rtl8192cu.ko` (also stock).
The init script has a hook for running a shell script from `/mnt/ramdisk/`. This can be used
for testing different modules etc.
The kernel command line has been modified to:
* disable DMA for the MUSB driver - otherwise the mass storage device is very unstable
* increase the size of dmesg buffer to 128k

View File

@ -1,34 +0,0 @@
#!/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()

View File

@ -1,53 +0,0 @@
diff -ur orig-ev3/etc/init.d/ev3init.sh dev-ev3/etc/init.d/ev3init.sh
--- orig-ev3/etc/init.d/ev3init.sh 1970-01-01 01:00:00.000000000 +0100
+++ dev-ev3/etc/init.d/ev3init.sh 2017-07-27 12:19:43.195041798 +0100
@@ -1,5 +1,7 @@
#!/bin/sh
+echo Y > /sys/module/printk/parameters/time
+
bluetoothd -n > /dev/null 2>&1 &
echo "Setting up VirtualDrive...";
@@ -60,3 +62,6 @@
sleep 2
hciattach /dev/ttyS2 texas 2000000 "flow" "nosleep" $STRING
sdptool add SP
+
+insmod /lib/modules/2.6.33-rc4/kernel/drivers/net/wireless/rtl8192cu.ko
+. /mnt/ramdisk/rc.local || :
Only in orig-ev3/home/root/lms2012/sys: exit~
diff -ur orig-ev3/home/root/lms2012/sys/init dev-ev3/home/root/lms2012/sys/init
--- orig-ev3/home/root/lms2012/sys/init 1970-01-01 01:00:00.000000000 +0100
+++ dev-ev3/home/root/lms2012/sys/init 2017-07-27 12:23:43.072605126 +0100
@@ -5,13 +5,15 @@
var=$(printf 'HostStr=%s SerialStr=%s' $(cat /home/root/lms2012/sys/settings/BrickName) $(cat /home/root/lms2012/sys/settings/BTser))
echo $var > /home/root/lms2012/sys/settings/UsbInfo.dat
+insmod ${PWD}/mod/nbd.ko
+${PWD}/uf2d
insmod ${PWD}/mod/d_iic.ko `cat /home/root/lms2012/sys/settings/HwId`
insmod ${PWD}/mod/d_uart.ko `cat /home/root/lms2012/sys/settings/HwId`
insmod ${PWD}/mod/d_power.ko `cat /home/root/lms2012/sys/settings/HwId`
insmod ${PWD}/mod/d_pwm.ko `cat /home/root/lms2012/sys/settings/HwId`
insmod ${PWD}/mod/d_ui.ko `cat /home/root/lms2012/sys/settings/HwId`
insmod ${PWD}/mod/d_analog.ko `cat /home/root/lms2012/sys/settings/HwId`
-insmod ${PWD}/mod/d_usbdev.ko `cat /home/root/lms2012/sys/settings/UsbInfo.dat`
+insmod ${PWD}/mod/d_usbdev.ko `cat /home/root/lms2012/sys/settings/UsbInfo.dat` file=/dev/nbd0
insmod ${PWD}/mod/d_usbhost.ko
insmod ${PWD}/mod/d_sound.ko `cat /home/root/lms2012/sys/settings/HwId`
insmod ${PWD}/mod/d_bt.ko `cat /home/root/lms2012/sys/settings/HwId`
@@ -29,6 +31,8 @@
chmod 666 /dev/lms_iic
chmod 666 /dev/lms_bt
+echo 4 > /proc/sys/kernel/printk
+
cd ..
ls -R > /dev/null
cd sys
Binary files orig-ev3/home/root/lms2012/sys/mod/d_usbdev.ko and dev-ev3/home/root/lms2012/sys/mod/d_usbdev.ko differ
Only in dev-ev3/home/root/lms2012/sys/mod: nbd.ko
Only in dev-ev3/home/root/lms2012/sys: uf2d
Only in orig-ev3/lib/modules/2.6.33-rc4/kernel/drivers/net/wireless: edimax01.ko
Only in dev-ev3/lib/modules/2.6.33-rc4/kernel/drivers/net/wireless: rtl8192cu.ko

View File

@ -1,55 +0,0 @@
#!/bin/sh
let fs = require("fs")
// we try to use shorter versions of all parameters for the additional parameters to fit
let bootargs = "mem=${memsize} initrd=${filesysaddr},${filesyssize} root=/dev/ram0 rw rootfstype=cramfs console=${console} ip=${ipaddr} lpj=747520 quiet"
let bootnews = "mem=64M initrd=0xC1180000,10M root=1:0 rw rootfstype=cramfs console=${console} lpj=747520 musb_hdrc.use_dma=0 log_buf_len=128k quiet"
let piggy = true
function build() {
if (bootnews.length > bootargs.length) {
console.log("args too long")
return
}
while (bootnews.length < bootargs.length)
bootnews += " "
let cr = fs.readFileSync("cram.bin")
if (cr.length > 10485760) {
console.log("too big by " + (cr.length - 10485760))
return
}
let img = fs.readFileSync("EV3 Firmware V1.09D.bin")
for (let i = 0; i < bootnews.length; ++i) {
if (img[0x21DDA + i] != bootargs.charCodeAt(i)) {
console.log("boot args mismatch")
return
}
img[0x21DDA + i] = bootnews.charCodeAt(i)
}
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 ? "piggy-patched.gzip" : "linux/arch/arm/boot/uImage")
off = piggy ? 0x0005540f : 0x00050000
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()

View File

@ -1,9 +0,0 @@
#!/bin/sh
# dd if=EV3\ Firmware\ V1.09D.bin of=orig.cram bs=65536 skip=37 count=400
sudo cp linux/pxt/uf2daemon/server dev-ev3/home/root/lms2012/sys/uf2d
sudo cp linux/pxt/kernel/d_usbdev.ko dev-ev3/home/root/lms2012/sys/mod/d_usbdev.ko
sudo chown -R root:root dev-ev3/home/root/lms2012
sudo mkfs.cramfs dev-ev3 cram.bin
node img
ls -l firmware.bin

View File

@ -1,8 +0,0 @@
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)

View File

@ -1,10 +0,0 @@
#!/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
#ev3duder exec 'echo . /mnt/ramdisk/prjs/ko/ins > /mnt/ramdisk/rc.local'

View File

@ -1,6 +0,0 @@
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

View File

@ -1,784 +0,0 @@
#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>
#include <sys/ioctl.h>
#include <string.h>
#include <errno.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 LOG
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", c->flags, (int)c->st.st_size, c->numclusters);
}
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", 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", 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", blkno);
int blkno0 = blkno;
for (ClusterData *c = firstCluster; c; c = c->cnext) {
// DBG("off=%d sz=%d", blkno, c->numclusters);
if (blkno >= c->numclusters) {
blkno -= c->numclusters;
continue;
}
// DBG("readbl off=%d %p", 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);
close(fd);
} 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);
}
}
char rbfPath[300];
uint8_t stopApp[] = {
0x05, 0x00, // size
0x00, 0x00, // seq. no.
0x3f, 0x3d, // usb magic,
0x02, // req. no.
};
uint8_t runStart[] = {0x00, 0x00, // size
0x00, 0x00, // seq. no.
0x00, 0x00, 0x08, // something
0xC0, 0x08, 0x82, 0x01, 0x00, 0x84};
uint8_t runEnd[] = {0x00, 0x60, 0x64, 0x03, 0x01, 0x60, 0x64, 0x00};
#define FEED_DATA _IOC(_IOC_WRITE, 't', 108, 1024)
void startRbf() {
char buf[1024];
memset(buf, 0, sizeof(buf));
memcpy(buf, stopApp, sizeof(stopApp));
int fd = open("/dev/lms_usbdev", O_RDWR);
ioctl(fd, FEED_DATA, buf);
usleep(500000);
int off = 0;
memcpy(buf + off, runStart, sizeof(runStart));
off += sizeof(runStart);
strcpy(buf + off, rbfPath);
off += strlen(rbfPath);
memcpy(buf + off, runEnd, sizeof(runEnd));
off += sizeof(runEnd);
off -= 2;
buf[0] = off & 0xff;
buf[1] = off >> 8;
ioctl(fd, FEED_DATA, buf);
close(fd);
}
#define MAX_BLOCKS 8000
typedef struct {
uint32_t numBlocks;
uint32_t numWritten;
uint8_t writtenMask[MAX_BLOCKS / 8 + 1];
} WriteState;
void restartProgram() {
if (!rbfPath[0])
exit(0);
startRbf();
exit(0); // causes parent to eject MSD etc
}
int numWrites = 0;
static WriteState wrState;
void write_block(uint32_t block_no, uint8_t *data) {
WriteState *state = &wrState;
UF2_Block *bl = (void *)data;
if (bl->magicStart0 == 0x20da6d81 && bl->magicStart1 == 0x747e09d4) {
DBG("restart req, #wr=%d", numWrites);
if (numWrites) {
exit(0);
}
return;
}
numWrites++;
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 && errno == ETXTBSY) {
unlink(fn);
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", bl->payloadSize, bl->targetAddr, fn);
write(fd, bl->data, bl->payloadSize);
close(fd);
if (strlen(fn) > 4 && !strcmp(fn + strlen(fn) - 4, ".rbf")) {
strcpy(rbfPath, 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++;
DBG("write %d/%d #%d", state->numWritten, state->numBlocks, bl->blockNo);
}
if (state->numWritten >= state->numBlocks) {
restartProgram();
}
}
} else {
// TODO timeout for restart?
}
}

View File

@ -1,231 +0,0 @@
#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 <stdarg.h>
#include "uf2.h"
const char *dev_file = "/dev/nbd0";
#define NUM_BLOCKS NUM_FAT_BLOCKS
uint64_t ntohll(uint64_t a) {
return ((uint64_t)ntohl(a & 0xffffffff) << 32) | ntohl(a >> 32);
}
#define htonll ntohll
void mylog(const char *fmt, ...) {
va_list args;
char *p, *p2;
va_start(args, fmt);
vasprintf(&p, fmt, args);
vprintf(fmt, args);
va_end(args);
if (p[0] != '<')
asprintf(&p2, "<6>%s\n", p);
else
asprintf(&p2, "%s\n", p);
int len = strlen(p2);
#ifdef X86
write(2, p2, len);
#else
int fd = open("/dev/kmsg", O_WRONLY);
write(fd, p2, len);
close(fd);
#endif
free(p);
free(p2);
}
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);
}
void handleread(int off, int len) {
uint8_t buf[512];
LOG("read @%d len=%d", off, len);
reply.error = 0; // htonl(EPERM);
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];
LOG("write @%d len=%d", 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(int argc, char **argv) {
#ifndef X86
daemon(0, 1);
#endif
if (argc > 1)
dev_file = argv[1];
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;
}

View File

@ -1,46 +0,0 @@
#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);
void mylog(const char *fmt, ...);
#define FAIL(args...) \
do { \
mylog("<4>" args); \
exit(1); \
} while (0)
#define LOG mylog
#endif

View File

@ -1,48 +0,0 @@
#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

View File

@ -1,106 +0,0 @@
#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

View File

@ -3,9 +3,3 @@
## Reference #reference
* [Reference](/reference)
* [input](/reference/input)
* [light](/reference/light)
* [music](/reference/music)
* [pins](/reference/pins)
* [control](/reference/control)
* [serial](/reference/serial)

47
docs/maker.md Normal file
View File

@ -0,0 +1,47 @@
# Maker Activites
These six activities require the LEGO® MINDSTORMS® Education EV3 Core Set (45544). Supporting materials for teachers and middle school students are provided, offering everything teachers and students need to explore their inner makers as they follow the design process to solve open-ended, themed challenges...
* [Download Curriculum Materials](https://education.lego.com/en-us/downloads/mindstorms-ev3)
## Activites
```codecard
[
{
"name": "Sound Machine",
"description": "Create instruments with your EV3 Brick!",
"url":"/maker/sound-machine",
"cardType": "example",
"imageUrl": "/static/maker/sound-machine.png"
},
{
"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": "Intruder Detector",
"description": "Raise the alarm when an intruder sneaks in",
"url":"/maker/intruder-detector",
"cardType": "example",
"imageUrl": "/static/maker/intruder-detector.png"
},
{
"name": "Puppet",
"description": "Build an automated puppet",
"url":"/maker/puppet",
"cardType": "example",
"imageUrl": "/static/maker/puppet.png"
}
]
```

View File

@ -0,0 +1,11 @@
# Intruder Detector
This program will activate an alarm when an object moves in front of the Ultrasonic Sensor.
TODO support for event when value changes
```blocks
input.ultrasonic4.onObjectNear(function () {
music.playSoundUntilDone(music.sounds(Sounds.PowerUp))
})
```

17
docs/maker/puppet.md Normal file
View File

@ -0,0 +1,17 @@
# Puppet
Use this program with the Programmable Brick and Large Motor.
```blocks
loops.forever(function () {
output.largeMotorA.setPower(30)
output.largeMotorA.on(true)
loops.pause(100)
output.largeMotorA.on(false)
music.playSoundUntilDone(music.sounds(Sounds.PowerUp))
output.largeMotorA.setPower(-30)
output.largeMotorA.on(true)
loops.pause(100)
output.largeMotorA.on(false)
})
```

View File

@ -0,0 +1,9 @@
# Security Gadget
This program will activate an alarm when an object is lifted from the Touch Sensor.
```blocks
input.touchSensor1.onEvent(TouchSensorEvent.Released, function () {
music.playSoundUntilDone(music.sounds(Sounds.PowerUp))
})
```

View File

@ -0,0 +1,12 @@
# Sound Machine
This example program combined with the small model will make a beat and rhythm on any surface when the program is run.
```blocks
loops.forever(function () {
output.motorA.on(50)
loops.pause(200)
output.motorA.on(100)
loops.pause(200)
})
```

View File

@ -0,0 +1,15 @@
# Sound Of Color
This program will play different sounds when the wheel is rotated. The sound is determined by which color is placed in front of the color Sensor.
```blocks
input.color3.onColorDetected(ColorSensorColor.Blue, function () {
music.playTone(Note.G4, music.beat(BeatFraction.Half))
})
input.color3.onColorDetected(ColorSensorColor.Red, function () {
music.playTone(Note.C5, music.beat(BeatFraction.Half))
})
input.color3.onColorDetected(ColorSensorColor.Green, function () {
music.playTone(Note.D5, music.beat(BeatFraction.Half))
})
```

View File

@ -1,19 +1,3 @@
# Reference
```namespaces
input.onGesture(Gesture.Shake, () => {})
light.showRing('red red red red red red red red red red')
music.playTone(0, 0)
pins.pulseDuration()
control.runInBackground(() => {})
serial.writeLine("");
```
## See Also
[blocks](/blocks), [JavaScript](/javascript), [input](/reference/input), [light](/reference/light), [music](/reference/music),
[control](/reference/control), [pins](/reference/pins), [serial](/reference/serial)
```package
circuit-playground
```
TODO

BIN
docs/static/hero.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

74
docs/static/lego-logo.svg vendored Normal file
View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
width="141.73"
height="141.731"
viewBox="0 0 141.73 141.73101"
enable-background="new 0 0 265.365 141.732"
xml:space="preserve"
inkscape:version="0.91 r13725"
sodipodi:docname="lego-logo.svg"><metadata
id="metadata26"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs24" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1199"
inkscape:window-height="604"
id="namedview22"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="1.6520876"
inkscape:cx="101.03204"
inkscape:cy="98.819336"
inkscape:window-x="372"
inkscape:window-y="149"
inkscape:window-maximized="0"
inkscape:current-layer="g6" /><g
id="product_logo" /><g
id="guides" /><g
id="LEGO_LOGO_SMALL_RGB"><g
id="g6"><path
d="m 0.961,0.948 0,139.839 139.84,0 0,-139.839 -139.84,0 z"
id="path8"
inkscape:connector-curvature="0"
style="fill:#ffffff" /><path
d="m 0.961,0.948 0,139.839 139.84,0 0,-139.839 -139.84,0 z m 130.536,58.127 c -0.23,4.356 -1.617,9.786 -2.839,13.414 -4.917,14.609 -10.618,23.666 -23.821,23.666 -3.887,0 -10.783,-1.031 -13.324,-7.947 l -0.602,-1.641 -1.082,1.371 C 85.7,93.168 79.564,96.186 72.998,96.217 67.96,96.24 63.912,94.553 61.293,91.334 l -0.718,-0.883 -0.765,0.844 c -2.797,3.088 -7.668,4.859 -13.364,4.859 -4.473,0 -8.335,-1.521 -10.876,-4.277 l -0.692,-0.752 -0.72,0.727 c -2.825,2.852 -7.276,4.289 -12.873,4.158 -6.79,-0.162 -10.924,-3.951 -11.058,-10.141 -0.205,-9.543 9.031,-29.622 12.854,-35.727 2.482,-4.078 5.895,-6.055 10.438,-6.055 3.092,0 5.207,0.646 6.463,1.977 1.144,1.211 1.37,2.232 1.472,4.688 l 0.131,3.175 1.676,-2.7 c 4.054,-6.532 10.773,-7.434 17.43,-7.434 4.628,0 8.667,1.702 10.289,4.336 l 0.599,0.971 0.866,-0.737 c 3.431,-2.916 8.271,-4.521 13.629,-4.521 5.849,0 10.099,1.454 12.634,4.322 0.576,0.651 0.957,1.106 1.486,2.219 l 0.651,1.366 0.977,-1.155 c 3.712,-4.39 8.779,-6.615 15.067,-6.615 4.98,0 8.761,1.324 11.235,3.935 3.104,3.271 3.547,7.875 3.373,11.161 z"
id="path10"
inkscape:connector-curvature="0"
style="fill:#f6ec36" /><path
d="m 0.961,0.948 0,139.839 139.84,0 0,-139.839 -139.84,0 z M 135.435,64.44 c -0.633,5.089 -4.072,14.518 -5.899,18.286 -4.903,10.102 -11.453,17.863 -24.074,17.863 -6.742,0 -12.288,-2.15 -15.531,-6.283 -4.749,4.162 -10.627,6.342 -16.956,6.342 -4.876,0 -9.185,-1.408 -12.471,-4.012 -3.626,2.555 -8.52,3.98 -13.943,3.98 -4.53,0 -8.606,-1.244 -11.796,-3.543 -3.529,2.342 -8.154,3.506 -13.583,3.377 C 12.149,100.237 5.912,94.507 5.733,86.188 5.497,75.137 14.803,54.911 19.189,47.907 c 3.282,-5.392 8.292,-8.293 14.431,-8.293 6.663,0 9.078,1.903 10.267,4.326 5.141,-4.366 11.956,-4.617 16.808,-4.617 5.356,0 8.717,1.422 11.575,3.697 3.948,-2.368 8.477,-3.599 13.871,-3.599 6.897,0 12.021,1.604 15.595,5.137 4.168,-3.469 9.388,-5.05 15.23,-5.05 7.725,0 12.808,2.786 15.793,6.94 4.203,5.859 3.451,11.757 2.676,17.992 z"
id="path12"
inkscape:connector-curvature="0"
style="fill:#d01012" /><path
d="m 0,0 0,141.731 141.73,0 L 141.73,0 0,0 Z m 139.781,1.952 0,137.832 -137.83,0 0,-137.832 137.83,0 z"
id="path14"
inkscape:connector-curvature="0" /><path
d="m 134.752,42.53 0,-0.965 0.655,0 c 0.479,0 0.728,0.168 0.728,0.479 0,0.247 -0.16,0.486 -0.647,0.486 l -0.736,0 z m 2.351,2.002 -0.408,-0.708 c -0.354,-0.619 -0.452,-0.717 -0.755,-0.823 l 0,-0.019 c 0.596,-0.07 0.95,-0.453 0.95,-0.983 0,-0.56 -0.354,-0.984 -1.109,-0.984 l -1.754,0 0,3.519 0.727,0 0,-1.441 0.133,0 c 0.311,0 0.435,0.035 0.576,0.176 0.142,0.144 0.354,0.443 0.479,0.69 l 0.284,0.575 0.877,-0.002 0,0 z m -1.731,-4.497 c 1.51,0 2.737,1.218 2.737,2.726 0,1.508 -1.229,2.731 -2.737,2.731 -1.506,0 -2.72,-1.225 -2.72,-2.731 0,-1.506 1.214,-2.726 2.72,-2.726 z m 0,-0.67 c -1.877,0 -3.392,1.516 -3.392,3.396 0,1.879 1.515,3.394 3.392,3.394 1.883,0 3.397,-1.515 3.397,-3.394 0.002,-1.882 -1.514,-3.396 -3.397,-3.396 z"
id="path16"
inkscape:connector-curvature="0" /><path
d="m 116.889,43.002 c -7.325,0 -12.386,2.904 -15.812,6.961 -0.579,-1.214 -1.019,-1.746 -1.638,-2.447 -2.805,-3.17 -7.313,-4.649 -13.364,-4.649 -5.912,0 -10.841,1.846 -14.263,4.754 -1.777,-2.89 -6.013,-4.803 -11.121,-4.803 -6.674,0 -13.946,0.944 -18.261,7.896 -0.104,-2.503 -0.33,-3.828 -1.737,-5.317 -1.71,-1.81 -4.477,-2.282 -7.173,-2.282 -4.912,0 -8.605,2.146 -11.266,6.515 -3.859,6.163 -13.212,26.441 -13.001,36.263 0.137,6.344 4.393,10.916 12.01,11.096 5.952,0.143 10.62,-1.449 13.59,-4.447 2.665,2.896 6.731,4.594 11.596,4.594 5.417,0 10.868,-1.627 14.088,-5.182 2.712,3.332 6.979,5.271 12.468,5.244 7.175,-0.035 13.477,-3.438 17.593,-8.652 2.259,6.148 7.985,8.59 14.241,8.59 13.709,0 19.729,-9.428 24.748,-24.332 1.13,-3.357 2.639,-8.963 2.889,-13.672 0.413,-7.839 -2.903,-16.13 -15.587,-16.13 z M 25.672,80.477 c 7.093,-1.232 8.876,1.332 8.653,3.707 -0.669,7.109 -7.191,8.699 -12.854,8.566 -4.107,-0.1 -7.8,-1.98 -7.903,-6.748 -0.18,-8.342 8.328,-27.641 12.333,-34.038 1.85,-3.037 4.104,-4.539 7.698,-4.539 3.406,0 4.25,1.749 4.2,3.844 -0.134,5.589 -9.164,22.574 -12.127,29.208 z M 48.77,73.925 c -0.469,1.27 -1.357,3.93 -2.076,6.75 2.328,-0.582 4.074,-0.986 7.065,-0.914 3.408,0.084 5.586,1.496 5.586,4.314 0,6.832 -7.551,8.838 -12.789,8.838 -5.751,0 -10.803,-3.275 -10.803,-9.564 0,-7.373 3.997,-18.553 7.748,-26.001 4.606,-9.146 9.312,-10.362 17.419,-10.362 3.562,0 7.667,1.524 7.667,4.888 0,4.662 -3.95,6.44 -7.866,6.665 -1.672,0.096 -4.246,0.188 -5.786,0.079 0,0 -1.303,1.985 -2.688,5.523 7.252,-1.021 10.327,0.625 9.103,4.82 -1.657,5.667 -6.567,6.04 -12.58,4.964 z M 84.438,56.293 c -1.961,0 -3.244,1.242 -4.198,2.583 -2.102,2.952 -6.656,14.781 -7.365,19.64 -0.486,3.328 0.951,4.006 2.522,4.006 2.52,0 5.345,-2.666 6.309,-7.064 0,0 -4.797,-0.117 -3.475,-4.371 1.285,-4.128 3.723,-5.022 7.764,-5.188 7.961,-0.325 7.175,5.553 6.538,8.688 -2.069,10.18 -9.314,18.355 -19.562,18.355 -7.016,0 -11.371,-3.881 -11.371,-11.035 0,-5.098 2.529,-13.101 4.534,-17.784 4.267,-9.968 8.742,-16.944 20.143,-16.944 6.84,0 12.235,2.458 11.444,8.866 -0.58,4.703 -2.934,7.465 -7.21,7.799 -1.196,0.093 -6.089,-0.031 -4.466,-4.66 0.565,-1.619 0.799,-2.891 -1.607,-2.891 z m 43.057,8.413 c -1.205,6.002 -3.916,13.101 -6.859,18.392 -4.801,8.633 -10.633,9.842 -15.723,9.781 -5.093,-0.061 -10.83,-1.941 -10.874,-9.795 -0.031,-5.639 2.401,-13.598 4.466,-18.815 3.599,-9.458 7.277,-17.17 18.904,-17.031 13.559,0.161 11.141,12.219 10.086,17.468 z M 115.993,56.49 c -1.164,-0.016 -2.18,0.212 -3.093,1.62 -2.051,2.657 -8.047,19.042 -7.941,22.31 0.038,1.174 0.687,2.201 2.133,2.201 1.659,0.002 2.581,-1.145 3.396,-2.529 1.887,-3.193 7.193,-17.676 7.339,-21.297 0.043,-1.055 -0.133,-2.284 -1.834,-2.305 z"
id="path18"
inkscape:connector-curvature="0" /></g></g></svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
docs/static/lego_education_logo.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
docs/static/maker/intruder-detector.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
docs/static/maker/puppet.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

BIN
docs/static/maker/security-gadget.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
docs/static/maker/sound-machine.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

BIN
docs/static/maker/sound-of-color.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

View File

@ -1,36 +1,52 @@
{
"Array": "Add, remove, and replace items in lists.\n\nAdd, remove, and replace items in lists.",
"Array.filter": "Returns the elements of an array that meet the condition specified in a callback function.",
"Array.filter": "Return the elements of an array that meet the condition specified in a callback function.",
"Array.filter|param|callbackfn": "A function that accepts up to two arguments. The filter method calls the callbackfn function one time for each element in the array.",
"Array.get": "Gets the value at a particular index",
"Array.get": "Get the value at a particular index",
"Array.get|param|index": "the zero-based position in the list of the item, eg: 0",
"Array.indexOf": "Returns the index of the first occurrence of a value in an array.",
"Array.indexOf": "Return the index of the first occurrence of a value in an array.",
"Array.indexOf|param|fromIndex": "The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.",
"Array.indexOf|param|item": "The value to locate in the array.",
"Array.insertAt": "Insert the value at a particular index, increases length by 1",
"Array.insertAt|param|index": "the zero-based position in the list to insert the value, eg: 0",
"Array.length": "Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.",
"Array.map": "Calls a defined callback function on each element of an array, and returns an array that contains the results.",
"Array.length": "Get or set the length of an array. This number is one more than the index of the last element the array.",
"Array.map": "Call a defined callback function on each element of an array, and return an array containing the results.",
"Array.map|param|callbackfn": "A function that accepts up to two arguments. The map method calls the callbackfn function one time for each element in the array.",
"Array.pop": "Removes the last element from an array and returns it.",
"Array.push": "Appends new elements to an array.",
"Array.reduce": "Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.",
"Array.pop": "Remove the last element from an array and return it.",
"Array.push": "Append a new element to an array.",
"Array.reduce": "Call the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.",
"Array.reduce|param|callbackfn": "A function that accepts up to three arguments. The reduce method calls the callbackfn function one time for each element in the array.",
"Array.reduce|param|initialValue": "Initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.",
"Array.removeAt": "Removes the object at position index.",
"Array.removeElement": "Removes the first occurence of an object. Returns true if removed.",
"Array.reverse": "Reverses the elements in an Array. The first array element becomes the last, and the last array element becomes the first.",
"Array.set": "Stores the value at a particular index",
"Array.removeAt": "Remove the element at a certain index.",
"Array.removeElement": "Remove the first occurence of an object. Returns true if removed.",
"Array.reverse": "Reverse the elements in an array. The first array element becomes the last, and the last array element becomes the first.",
"Array.set": "Store a value at a particular index",
"Array.set|param|index": "the zero-based position in the list to store the value, eg: 0",
"Array.shift": "Removes the first element from an array and returns that element. This method changes the length of the array.",
"Array.slice": "Returns a section of an array.",
"Array.shift": "Remove the first element from an array and return it. This method changes the length of the array.",
"Array.slice": "Return a section of an array.",
"Array.slice|param|end": "The end of the specified portion of the array. eg: 0",
"Array.slice|param|start": "The beginning of the specified portion of the array. eg: 0",
"Array.sort": "Sorts the elements of an array in place and returns the array. The sort is not necessarily stable.",
"Array.splice": "Removes elements from an array.",
"Array.sort": "Sort the elements of an array in place and returns the array. The sort is not necessarily stable.",
"Array.splice": "Remove elements from an array.",
"Array.splice|param|deleteCount": "The number of elements to remove. eg: 0",
"Array.splice|param|start": "The zero-based location in the array from which to start removing elements. eg: 0",
"Array.unshift": "Adds one element to the beginning of an array and returns the new length of the array.",
"Array.unshift": "Add one element to the beginning of an array and return the new length of the array.",
"Boolean.toString": "Returns a string representation of an object.",
"Buffer.fill": "Fill (a fragment) of the buffer with given value.",
"Buffer.getNumber": "Read a number in specified format from the buffer.",
"Buffer.length": "Returns the length of a Buffer object.",
"Buffer.rotate": "Rotate buffer left in place.\n\n\n\nstart. eg: -1",
"Buffer.rotate|param|length": "number of elements in buffer. If negative, length is set as the buffer length minus",
"Buffer.rotate|param|offset": "number of bytes to shift; use negative value to shift right",
"Buffer.rotate|param|start": "start offset in buffer. Default is 0.",
"Buffer.setNumber": "Write a number in specified format in the buffer.",
"Buffer.shift": "Shift buffer left in place, with zero padding.\n\n\n\nstart. eg: -1",
"Buffer.shift|param|length": "number of elements in buffer. If negative, length is set as the buffer length minus",
"Buffer.shift|param|offset": "number of bytes to shift; use negative value to shift right",
"Buffer.shift|param|start": "start offset in buffer. Default is 0.",
"Buffer.slice": "Return a copy of a fragment of a buffer.",
"Buffer.toHex": "Convert a buffer to its hexadecimal representation.",
"Buffer.write": "Write contents of `src` at `dstOffset` in current buffer.",
"Math": "More complex operations with numbers.",
"Math.abs": "Returns the absolute value of a number (the value without regard to whether it is positive or negative).\nFor example, the absolute value of -5 is the same as the absolute value of 5.",
"Math.abs|param|x": "A numeric expression for which the absolute value is needed.",
@ -91,23 +107,26 @@
"Math.tan|param|x": "An angle in radians",
"Math.trunc": "Returns the number with the decimal part truncated.",
"Math.trunc|param|x": "A numeric expression.",
"Number.toString": "Returns a string representation of a number.",
"String": "Combine, split, and search text strings.\n\nCombine, split, and search text strings.",
"String.charAt": "Returns the character at the specified index.",
"String.charAt": "Return the character at the specified index.",
"String.charAt|param|index": "The zero-based index of the desired character.",
"String.charCodeAt": "Returns the Unicode value of the character at the specified location.",
"String.charCodeAt": "Return the Unicode value of the character at the specified location.",
"String.charCodeAt|param|index": "The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.",
"String.compare": "Determines whether relative order of two strings (in ASCII encoding).",
"String.compare": "See how the order of characters in two strings is different (in ASCII encoding).",
"String.compare|param|that": "String to compare to target string",
"String.concat": "Returns a string that contains the concatenation of two or more strings.",
"String.concat|param|other": "The string to append to the end of the string.",
"String.fromCharCode": "Make a string from the given ASCII character code.",
"String.isEmpty": "Returns a value indicating if the string is empty",
"String.length": "Returns the length of a String object.",
"String.substr": "Return substring of the current string.",
"String.substr": "Return a substring of the current string.",
"String.substr|param|length": "number of characters to extract",
"String.substr|param|start": "first character index; can be negative from counting from the end, eg:0",
"control": "Program controls and events.",
"control.assert": "Display specified error code and stop the program.",
"control.AnimationQueue.cancel": "Cancels the current running animation and clears the queue",
"control.AnimationQueue.runUntilDone": "Runs 'render' in a loop until it returns false or the 'stop' function is called",
"control.assert": "Display an error code and stop the program when the assertion is `false`.",
"control.deviceSerialNumber": "Derive a unique, consistent serial number of this device from internal data.",
"control.millis": "Gets the number of milliseconds elapsed since power on.",
"control.onEvent": "Run code when a registered event happens.",
@ -119,9 +138,13 @@
"control.waitForEvent": "Blocks the calling thread until the specified event is raised.",
"control.waitMicros": "Block the current fiber for the given microseconds",
"control.waitMicros|param|micros": "number of micro-seconds to wait. eg: 4",
"hex": "Tagged hex literal converter",
"loops.forever": "Repeats the code forever in the background. On each iteration, allows other codes to run.",
"loops.pause": "Pause for the specified time in milliseconds",
"loops.pause|param|ms": "how long to pause for, eg: 100, 200, 500, 1000, 2000",
"loops.timePicker": "Get the time field editor",
"loops.timePicker|param|ms": "time duration in milliseconds, eg: 500, 1000",
"parseInt": "Convert a string to an integer.",
"serial": "Reading and writing data over a serial connection.",
"serial.writeBuffer": "Send a buffer across the serial connection.",
"serial.writeLine": "Write a line of text to the serial port.",

View File

@ -19,6 +19,7 @@
"String.length|block": "length of %VALUE",
"String.substr|block": "substring of %this=text|from %start|of length %length",
"String|block": "String",
"control.assert|block": "assert %cond|with value %code",
"control.deviceSerialNumber|block": "device serial number",
"control.millis|block": "millis (ms)",
"control.onEvent|block": "on event|from %src|with value %value",
@ -29,8 +30,10 @@
"control.waitMicros|block": "wait (µs)%micros",
"control|block": "control",
"loops.forever|block": "forever",
"loops.pause|block": "pause (ms) %pause",
"loops.pause|block": "pause %ms=timePicker|ms",
"loops.timePicker|block": "%ms",
"loops|block": "loops",
"parseInt|block": "parse to integer %text",
"serial.writeBuffer|block": "serial|write buffer %buffer",
"serial.writeLine|block": "serial|write line %text",
"serial.writeNumber|block": "serial|write number %value",
@ -39,9 +42,13 @@
"serial|block": "serial",
"{id:category}Array": "Array",
"{id:category}Arrays": "Arrays",
"{id:category}Boolean": "Boolean",
"{id:category}Buffer": "Buffer",
"{id:category}Control": "Control",
"{id:category}Helpers": "Helpers",
"{id:category}Loops": "Loops",
"{id:category}Math": "Math",
"{id:category}Number": "Number",
"{id:category}Serial": "Serial",
"{id:category}String": "String",
"{id:category}Text": "Text"

11
libs/base/shims.d.ts vendored
View File

@ -70,7 +70,7 @@ declare namespace loops {
* Repeats the code forever in the background. On each iteration, allows other codes to run.
* @param body code to execute
*/
//% help=loops/forever weight=100 blockGap=8
//% help=loops/forever weight=100 afterOnStart=true
//% blockId=forever block="forever" blockAllowMultiple=1 shim=loops::forever
function forever(a: () => void): void;
@ -79,7 +79,7 @@ declare namespace loops {
* @param ms how long to pause for, eg: 100, 200, 500, 1000, 2000
*/
//% help=loops/pause weight=99
//% async block="pause (ms) %pause"
//% async block="pause %ms=timePicker|ms"
//% blockId=device_pause shim=loops::pause
function pause(ms: int32): void;
}
@ -120,7 +120,7 @@ declare namespace control {
/**
* Run other code in the background.
*/
//% help=control/run-in-background blockAllowMultiple=1
//% help=control/run-in-background blockAllowMultiple=1 afterOnStart=true
//% blockId="control_run_in_background" block="run in background" blockGap=8 shim=control::runInBackground
function runInBackground(a: () => void): void;
@ -134,7 +134,8 @@ declare namespace control {
/**
* Derive a unique, consistent serial number of this device from internal data.
*/
//% blockId="control_device_serial_number" block="device serial number" weight=9 shim=control::deviceSerialNumber
//% blockId="control_device_serial_number" block="device serial number" weight=9
//% help=control/device-serial-number shim=control::deviceSerialNumber
function deviceSerialNumber(): int32;
}
declare namespace serial {
@ -150,7 +151,7 @@ declare namespace serial {
/**
* Send a buffer across the serial connection.
*/
//% help=serial/write-buffer advanced=true weight=6
//% help=serial/write-buffer weight=6
//% blockId=serial_writebuffer block="serial|write buffer %buffer" shim=serial::writeBuffer
function writeBuffer(buffer: Buffer): void;
}

View File

@ -1,4 +1,15 @@
{
"ButtonEvent": "User interaction on buttons",
"Draw": "Drawing modes",
"LightsPattern": "Patterns for lights under the buttons.",
"MMap.getNumber": "Read a number in specified format from the buffer.",
"MMap.ioctl": "Perform ioctl(2) on the underlaying file",
"MMap.length": "Returns the length of a Buffer object.",
"MMap.read": "Perform read(2) on the underlaying file",
"MMap.setNumber": "Write a number in specified format in the buffer.",
"MMap.slice": "Read a range of bytes into a buffer.",
"MMap.write": "Perform write(2) on the underlaying file",
"TouchSensorEvent": "Touch sensor interactions",
"control": "Program controls and events.",
"control.allocateNotifyEvent": "Allocates the next user notification event",
"control.deviceFirmwareVersion": "Determine the version of system software currently running.",
@ -7,46 +18,73 @@
"control.raiseEvent": "Announce that an event happened to registered handlers.",
"control.raiseEvent|param|src": "ID of the Component that generated the event",
"control.raiseEvent|param|value": "Component specific code indicating the cause of the event.",
"input": "Respond to and read data from buttons and sensors.",
"input.Button": "Generic button class, for device buttons and sensors.",
"input.buttonDown": "Down button.",
"input.buttonEnter": "Enter button.",
"input.buttonLeft": "Left button.",
"input.buttonRight": "Right button.",
"input.buttonUp": "Up button.",
"input.remoteBottomLeft": "Remote bottom-left button.",
"input.remoteBottomRight": "Remote bottom-right button.",
"input.remoteCenter": "Remote beacon (center) button.",
"input.remoteTopLeft": "Remote top-left button.",
"input.remoteTopRight": "Remote top-right button.",
"input.Button.isPressed": "Check if button is currently pressed or not.",
"input.Button.onEvent": "Do something when a button or sensor is clicked, up or down.",
"input.Button.onEvent|param|body": "code to run when the event is raised",
"input.Button.wasPressed": "See if the button was pressed again since the last time you checked.",
"input.ColorSensor.ambientLight": "Get current ambient light value from the color sensor.",
"input.ColorSensor.color": "Get the current color from the color sensor.",
"input.ColorSensor.onColorDetected": "Registers code to run when the given color is detected",
"input.ColorSensor.onColorDetected|param|color": "the color to dtect",
"input.ColorSensor.onColorDetected|param|handler": "the code to run when detected",
"input.ColorSensor.reflectedLight": "Get current reflected light value from the color sensor.",
"input.GyroSensor.angle": "Get the current angle from the gyroscope.",
"input.GyroSensor.rate": "Get the current rotation rate from the gyroscope.",
"input.InfraredSensor.onObjectNear": "Registers code to run when an object is getting near.",
"input.InfraredSensor.onObjectNear|param|handler": "the code to run when detected",
"input.InfraredSensor.proximity": "Get the promixity measured by the infrared sensor, from ``0`` (close) to ``100`` (far)",
"input.InfraredSensor.remoteCommand": "Get the remote commandreceived the infrared sensor.",
"input.RemoteInfraredBeaconButton.isPressed": "Check if a remote button is currently pressed or not.",
"input.RemoteInfraredBeaconButton.onEvent": "Do something when a button or sensor is clicked, up or down",
"input.RemoteInfraredBeaconButton.onEvent|param|body": "code to run when the event is raised",
"input.RemoteInfraredBeaconButton.wasPressed": "See if the remote button was pressed again since the last time you checked.",
"input.TouchSensor.isTouched": "Check if touch sensor is touched.",
"input.TouchSensor.onEvent": "Do something when a touch sensor is touched...",
"input.TouchSensor.onEvent|param|body": "code to run when the event is raised",
"input.UltraSonicSensor.distance": "Gets the distance from the sonar in millimeters",
"input.UltraSonicSensor.onObjectNear": "Registers code to run when the given color is close",
"input.UltraSonicSensor.onObjectNear|param|handler": "the code to run when detected",
"input.buttonDown": "Down button on the EV3 Brick.",
"input.buttonEnter": "Enter button on the EV3 Brick.",
"input.buttonLeft": "Left button on the EV3 Brick.",
"input.buttonRight": "Right button on the EV3 Brick.",
"input.buttonUp": "Up button on the EV3 Brick.",
"input.remoteButtonBottomLeft": "Remote bottom-left button.",
"input.remoteButtonBottomRight": "Remote bottom-right button.",
"input.remoteButtonCenter": "Remote beacon (center) button.",
"input.remoteButtonTopLeft": "Remote top-left button.",
"input.remoteButtonTopRight": "Remote top-right button.",
"output.Motor.clearCount": "Clears the motor count",
"output.Motor.count": "Gets motor step count.",
"output.Motor.on": "Power on or off the motor.",
"output.Motor.reset": "Resets the motor.",
"output.Motor.setBrake": "Sets the automatic brake on or off when the motor is off",
"output.Motor.setBrake|param|brake": "a value indicating if the motor should break when off",
"output.Motor.setPower": "Sets the motor power level from ``-100`` to ``100``.",
"output.Motor.setPower|param|power": "the desired speed to use. eg: 50",
"output.Motor.setReversed": "Reverses the motor polarity",
"output.Motor.speed": "Gets motor actual speed.",
"output.Motor.tachoCount": "Gets motor tacho count.",
"output.createBuffer": "Create a new zero-initialized buffer.",
"output.createBuffer|param|size": "number of bytes in the buffer",
"output.getCurrentSpeed": "Get motor speed.",
"output.getCurrentSpeed|param|out": "the output connection that the motor is connected to",
"output.getPattern": "Pattern block.",
"output.getPattern|param|pattern": "the lights pattern to use. eg: LightsPattern.Green",
"output.setLights": "Set lights.",
"output.setLights|param|pattern": "the lights pattern to use.",
"output.setPower": "Set motor power.",
"output.setPower|param|out": "the output connection that the motor is connected to",
"output.setPower|param|power": "the desired power to use. eg: 100",
"output.setSpeed": "Set motor speed.",
"output.setSpeed|param|out": "the output connection that the motor is connected to",
"output.setSpeed|param|speed": "the desired speed to use. eg: 100",
"output.start": "Turn motor on.",
"output.start|param|out": "the output connection that the motor is connected to",
"output.stop": "Turn motor off.",
"output.stop|param|out": "the output connection that the motor is connected to",
"output.turn": "Turn a motor on for a specified number of milliseconds.",
"output.turn|param|ms": "the number of milliseconds to turn the motor on, eg: 500",
"output.turn|param|out": "the output connection that the motor is connected to",
"output.turn|param|useBrake": "whether or not to use the brake, defaults to false",
"output.pattern": "Pattern block.",
"output.pattern|param|pattern": "the lights pattern to use. eg: LightsPattern.Green",
"output.setStatusLight": "Set lights.",
"output.setStatusLight|param|pattern": "the lights pattern to use.",
"output.stopAllMotors": "Stops all motors",
"screen.clear": "Clear screen and reset font to normal.",
"screen.doubleIcon": "Double size of an icon.",
"screen.drawIcon": "Draw an icon on the screen.",
"screen.drawText": "Show text on the screen.",
"screen.drawText|param|text": "the text to print on the screen, eg: \"Hello world\"",
"screen.drawText|param|x": "the starting position's x coordinate, eg: 0",
"screen.drawText|param|y": "the starting position's x coordinate, eg: 0",
"screen.print": "Show text on the screen.",
"screen.print|param|text": "the text to print on the screen, eg: \"Hello world\"",
"screen.print|param|x": "the starting position's x coordinate, eg: 0",
"screen.print|param|y": "the starting position's x coordinate, eg: 0",
"screen.setPixel": "Sets a pixel on or off",
"screen.setPixel|param|on": "a value indicating if the pixel should be on or off",
"screen.setPixel|param|x": "the starting position's x coordinate, eg: 0",
"screen.setPixel|param|y": "the starting position's x coordinate, eg: 0",
"serial": "Reading and writing data over a serial connection.",
"serial.writeDmesg": "Send DMESG debug buffer over serial."
}

View File

@ -1,39 +1,122 @@
{
"ButtonEvent.Click|block": "click",
"ButtonEvent.Down|block": "down",
"ButtonEvent.LongClick|block": "long click",
"ButtonEvent.Up|block": "up",
"ColorSensorColor.Black|block": "black",
"ColorSensorColor.Blue|block": "blue",
"ColorSensorColor.Brown|block": "brown",
"ColorSensorColor.Green|block": "green",
"ColorSensorColor.None|block": "none",
"ColorSensorColor.Red|block": "red",
"ColorSensorColor.White|block": "white",
"ColorSensorColor.Yellow|block": "yellow",
"LightsPattern.GreenFlash|block": "Flashing Green",
"LightsPattern.GreenPulse|block": "Pulsing Green",
"LightsPattern.Green|block": "Green",
"LightsPattern.Off|block": "Off",
"LightsPattern.OrangeFlash|block": "Flashing Orange",
"LightsPattern.OrangePulse|block": "Pulsing Orange",
"LightsPattern.Orange|block": "Orange",
"LightsPattern.RedFlash|block": "Flashing Red",
"LightsPattern.RedPulse|block": "Pulsing Red",
"LightsPattern.Red|block": "Red",
"Output.ALL|block": "All",
"Output.A|block": "A",
"Output.B|block": "B",
"Output.C|block": "C",
"Output.D|block": "D",
"PromixityEvent.ObjectDetected|block": "object detected",
"PromixityEvent.ObjectNear|block": "object near",
"TouchSensorEvent.Bumped|block": "bumped",
"TouchSensorEvent.Pressed|block": "pressed",
"TouchSensorEvent.Released|block": "released",
"control.raiseEvent|block": "raise event|from %src|with value %value",
"control|block": "control",
"input.buttonDown|block": "button down",
"input.buttonEnter|block": "button enter",
"input.buttonLeft|block": "button left",
"input.buttonRight|block": "button right",
"input.buttonUp|block": "button up",
"input.remoteBottomLeft|block": "remote bottom-left",
"input.remoteBottomRight|block": "remote bottom-right",
"input.remoteCenter|block": "remote center",
"input.remoteTopLeft|block": "remote top-left",
"input.remoteTopRight|block": "remote top-right",
"input.Button.isPressed|block": "%button|is pressed",
"input.Button.onEvent|block": "on %button|%event",
"input.Button.wasPressed|block": "%button|was pressed",
"input.ColorSensor.ambientLight|block": "%color| ambient light",
"input.ColorSensor.color|block": "%color| color",
"input.ColorSensor.onColorDetected|block": "on %sensor|detected %color",
"input.ColorSensor.reflectedLight|block": "%color| reflected light",
"input.GyroSensor.angle|block": "%sensor|angle",
"input.GyroSensor.rate|block": "%sensor|rotation rate",
"input.InfraredSensor.onObjectNear|block": "on %sensor|object near",
"input.InfraredSensor.proximity|block": "%infrared|proximity",
"input.InfraredSensor.remoteCommand|block": "%infrared|remote command",
"input.RemoteInfraredBeaconButton.isPressed|block": "%button|is pressed",
"input.RemoteInfraredBeaconButton.onEvent|block": "on %button|%event",
"input.RemoteInfraredBeaconButton.wasPressed|block": "%button|was pressed",
"input.TouchSensor.isTouched|block": "%sensor|is touched",
"input.TouchSensor.onEvent|block": "on %sensor|%event",
"input.UltraSonicSensor.distance|block": "%sensor|distance",
"input.UltraSonicSensor.onObjectNear|block": "on %sensor|object near",
"input.buttonDown|block": "brick button down",
"input.buttonEnter|block": "brick button enter",
"input.buttonLeft|block": "brick button left",
"input.buttonRight|block": "brick button right",
"input.buttonUp|block": "brick button up",
"input.color1|block": "color sensor 1",
"input.color2|block": "color sensor 2",
"input.color3|block": "color sensor 3",
"input.color4|block": "color sensor 4",
"input.gyro1|block": "gyro sensor 1",
"input.gyro2|block": "gyro sensor 2",
"input.gyro3|block": "gyro sensor 3",
"input.gyro4|block": "gyro sensor 4",
"input.infraredSensor1|block": "infrared sensor 1",
"input.infraredSensor2|block": "infrared sensor 2",
"input.infraredSensor3|block": "infrared sensor 3",
"input.infraredSensor4|block": "infrared sensor 4",
"input.remoteButtonBottomLeft|block": "remote button bottom-left",
"input.remoteButtonBottomRight|block": "remote button bottom-right",
"input.remoteButtonCenter|block": "remote button center",
"input.remoteButtonTopLeft|block": "remote button top-left",
"input.remoteButtonTopRight|block": "remote button top-right",
"input.touchSensor1|block": "touch sensor 1",
"input.touchSensor2|block": "touch sensor 2",
"input.touchSensor3|block": "touch sensor 3",
"input.touchSensor4|block": "touch sensor 4",
"input.ultrasonic1|block": "ultrasonic sensor 1",
"input.ultrasonic2|block": "ultrasonic sensor 2",
"input.ultrasonic3|block": "ultrasonic sensor 3",
"input.ultrasonic4|block": "ultrasonic sensor 4",
"input|block": "input",
"output.getCurrentSpeed|block": "motor %out|speed",
"output.getPattern|block": "%pattern",
"output.setLights|block": "set status light %pattern=led_pattern",
"output.setPower|block": "set motor %out| power to %power",
"output.setSpeed|block": "set motor %out| speed to %speed",
"output.start|block": "turn motor %out|on",
"output.stop|block": "turn motor %out|off",
"output.turn|block": "turn motor %out| on for %ms|milliseconds",
"output.Motor.count|block": "%motor|count",
"output.Motor.on|block": "%motor|%onOrOff",
"output.Motor.setBrake|block": "%motor|set brake %brake",
"output.Motor.setPower|block": "%motor|set power to %speed",
"output.Motor.setReversed|block": "%motor|set reversed %reversed",
"output.Motor.speed|block": "%motor|speed",
"output.Motor.tachoCount|block": "%motor|tacho count",
"output.largeMotorA|block": "large motor A",
"output.largeMotorB|block": "large motor B",
"output.largeMotorC|block": "large motor C",
"output.largeMotorD|block": "large motor D",
"output.mediumMotorA|block": "medium motor A",
"output.mediumMotorB|block": "medium motor B",
"output.mediumMotorC|block": "medium motor C",
"output.mediumMotorD|block": "medium motor D",
"output.pattern|block": "%pattern",
"output.setStatusLight|block": "set status light %pattern=led_pattern",
"output.stopAllMotors|block": "stop all motors",
"output|block": "output",
"screen.drawText|block": "print %text| at x: %x| y: %y",
"screen.print|block": "print %text| at x: %x| y: %y",
"screen.setPixel|block": "set pixel %on| at x: %x| y: %y",
"screen|block": "screen",
"serial|block": "serial",
"{id:category}Control": "Control",
"{id:category}Input": "Input",
"{id:category}MMap": "MMap",
"{id:category}Output": "Output",
"{id:category}Screen": "Screen",
"{id:category}Serial": "Serial",
"{id:group}Lights": "Lights",
"{id:group}Brick": "Brick",
"{id:group}Color Sensor": "Color Sensor",
"{id:group}Gyro Sensor": "Gyro Sensor",
"{id:group}Infrared Sensor": "Infrared Sensor",
"{id:group}Motors": "Motors",
"{id:group}Screen": "Screen"
"{id:group}Remote Infrared Beacon": "Remote Infrared Beacon",
"{id:group}Touch Sensor": "Touch Sensor",
"{id:group}Ultrasonic Sensor": "Ultrasonic Sensor"
}

View File

@ -3,15 +3,35 @@
* Patterns for lights under the buttons.
*/
const enum LightsPattern {
//% block=Off enumval=0
//% blockIdentity=output.pattern
Off = 0,
//% block=Green enumval=1
//% blockIdentity=output.pattern
Green = 1,
//% block=Red enumval=2
//% blockIdentity=output.pattern
Red = 2,
//% block=Orange enumval=3
//% blockIdentity=output.pattern
Orange = 3,
//% block="Flashing Green" enumval=4
//% blockIdentity=output.pattern
GreenFlash = 4,
//% block="Flashing Red" enumval=5
//% blockIdentity=output.pattern
RedFlash = 5,
//% block="Flashing Orange" enumval=6
//% blockIdentity=output.pattern
OrangeFlash = 6,
//% block="Pulsing Green" enumval=7
//% blockIdentity=output.pattern
GreenPulse = 7,
//% block="Pulsing Red" enumval=8
//% blockIdentity=output.pattern
RedPulse = 8,
//% block="Pulsing Orange" enumval=9
//% blockIdentity=output.pattern
OrangePulse = 9,
}
@ -21,8 +41,6 @@ const enum LightsPattern {
const enum ButtonEvent {
//% block="click"
Click = 1,
//% block="long click"
LongClick = 2,
//% block="up"
Up = 3,
//% block="down"
@ -47,7 +65,7 @@ namespace input {
}
//% hidden
update(curr: boolean) {
_update(curr: boolean) {
if (this._isPressed == curr) return
this._isPressed = curr
if (curr) {
@ -56,7 +74,8 @@ namespace input {
} else {
control.raiseEvent(this._id, ButtonEvent.Up)
let delta = control.millis() - this.downTime
control.raiseEvent(this._id, delta > 500 ? ButtonEvent.LongClick : ButtonEvent.Click)
control.raiseEvent(this._id, ButtonEvent.Click)
//control.raiseEvent(this._id, delta > 500 ? ButtonEvent.LongClick : ButtonEvent.Click)
}
}
@ -64,16 +83,13 @@ namespace input {
* Check if button is currently pressed or not.
* @param button the button to query the request
*/
//% help=input/button/is-pressed weight=79
//% help=input/button/is-pressed
//% block="%button|is pressed"
//% blockId=buttonIsPressed
//% blockGap=8
//% parts="buttonpair"
//% parts="brick"
//% blockNamespace=input
//% group="Brick buttons"
//% button.fieldEditor="gridpicker"
//% button.fieldOptions.width=220
//% button.fieldOptions.columns=3
//% weight=81 blockGap=8
//% group="Brick"
isPressed() {
return this._isPressed
}
@ -82,15 +98,13 @@ namespace input {
* See if the button was pressed again since the last time you checked.
* @param button the button to query the request
*/
//% help=input/button/was-pressed weight=78
//% help=input/button/was-pressed
//% block="%button|was pressed"
//% blockId=buttonWasPressed
//% parts="buttonpair" blockGap=8
//% blockNamespace=input advanced=true
//% group="Brick buttons"
//% button.fieldEditor="gridpicker"
//% button.fieldOptions.width=220
//% button.fieldOptions.columns=3
//% parts="brick"
//% blockNamespace=input
//% weight=80 blockGap=8
//% group="Brick"
wasPressed() {
const r = this._wasPressed
this._wasPressed = false
@ -98,19 +112,17 @@ namespace input {
}
/**
* Do something when a button or sensor is clicked, double clicked, etc...
* Do something when a button or sensor is clicked, up or down.
* @param button the button that needs to be clicked or used
* @param event the kind of button gesture that needs to be detected
* @param body code to run when the event is raised
*/
//% help=input/button/on-event weight=99 blockGap=8
//% help=input/button/on-event
//% blockId=buttonEvent block="on %button|%event"
//% parts="buttonpair"
//% parts="brick"
//% blockNamespace=input
//% group="Brick buttons"
//% button.fieldEditor="gridpicker"
//% button.fieldOptions.width=220
//% button.fieldOptions.columns=3
//% weight=99 blockGap=8
//% group="Brick"
onEvent(ev: ButtonEvent, body: () => void) {
control.onEvent(this._id, ev, body)
}
@ -147,7 +159,7 @@ namespace input {
if (curr & DAL.BUTTON_ID_ESCAPE)
control.reset()
for (let b of buttons)
b.update(!!(curr & b.mask))
b._update(!!(curr & b.mask))
})
control.dmesg("runtime started, " + control.deviceFirmwareVersion())
}
@ -164,35 +176,36 @@ namespace input {
initBtns() // always ON as it handles ESCAPE button
/**
* Left button.
* Enter button on the EV3 Brick.
*/
//% whenUsed block="button left" weight=95 fixedInstance
//% whenUsed block="brick button enter" weight=95 fixedInstance
export const buttonEnter: Button = new DevButton(DAL.BUTTON_ID_ENTER)
/**
* Left button on the EV3 Brick.
*/
//% whenUsed block="brick button left" weight=95 fixedInstance
export const buttonLeft: Button = new DevButton(DAL.BUTTON_ID_LEFT)
/**
* Right button.
* Right button on the EV3 Brick.
*/
//% whenUsed block="button right" weight=94 fixedInstance
//% whenUsed block="brick button right" weight=94 fixedInstance
export const buttonRight: Button = new DevButton(DAL.BUTTON_ID_RIGHT)
/**
* Up button.
* Up button on the EV3 Brick.
*/
//% whenUsed block="button up" weight=95 fixedInstance
//% whenUsed block="brick button up" weight=95 fixedInstance
export const buttonUp: Button = new DevButton(DAL.BUTTON_ID_UP)
/**
* Down button.
* Down button on the EV3 Brick.
*/
//% whenUsed block="button down" weight=95 fixedInstance
//% whenUsed block="brick button down" weight=95 fixedInstance
export const buttonDown: Button = new DevButton(DAL.BUTTON_ID_DOWN)
/**
* Enter button.
*/
//% whenUsed block="button enter" weight=95 fixedInstance
export const buttonEnter: Button = new DevButton(DAL.BUTTON_ID_ENTER)
}
@ -221,8 +234,8 @@ namespace output {
* @param pattern the lights pattern to use.
*/
//% blockId=setLights block="set status light %pattern=led_pattern"
//% weight=100 group="Lights"
export function setLights(pattern: number): void {
//% weight=100 group="Brick"
export function setStatusLight(pattern: number): void {
if (currPattern === pattern)
return
currPattern = pattern
@ -238,8 +251,8 @@ namespace output {
*/
//% blockId=led_pattern block="%pattern"
//% shim=TD_ID colorSecondary="#6e9a36"
//% blockHidden=true
export function getPattern(pattern: LightsPattern): number {
//% blockHidden=true useEnumVal=1 pattern.fieldOptions.decompileLiterals=1
export function pattern(pattern: LightsPattern): number {
return pattern;
}
}

View File

@ -9,21 +9,30 @@ const enum ColorSensorMode {
}
const enum ColorSensorColor {
//% block="none"
None,
//% block="black"
Black,
//% block="blue"
Blue,
//% block="green"
Green,
//% block="yellow"
Yellow,
//% block="red"
Red,
//% block="white"
White,
//% block="brown"
Brown,
}
namespace input {
//% fixedInstances
export class ColorSensor extends internal.UartSensor {
constructor() {
super()
constructor(port: number) {
super(port)
}
_deviceType() {
@ -34,22 +43,93 @@ namespace input {
this._setMode(m)
}
getAmbientLight() {
_query() {
if (this.mode == ColorSensorMode.Color)
return this.getNumber(NumberFormat.UInt8LE, 0)
return 0
}
_update(prev: number, curr: number) {
control.raiseEvent(this._id, curr);
}
/**
* Registers code to run when the given color is detected
* @param color the color to dtect
* @param handler the code to run when detected
*/
//% help=input/color/on-color-detected
//% block="on %sensor|detected %color"
//% blockId=colorOnColorDetected
//% parts="colorsensor"
//% blockNamespace=input
//% weight=100 blockGap=8
//% group="Color Sensor"
onColorDetected(color: ColorSensorColor, handler: () => void) {
control.onEvent(this._id, <number>color, handler);
this.setMode(ColorSensorMode.Color)
if (this.color() == color)
control.runInBackground(handler)
}
/**
* Get current ambient light value from the color sensor.
* @param color the color sensor to query the request
*/
//% help=input/color/ambient-light
//% block="%color| ambient light"
//% blockId=colorGetAmbient
//% parts="colorsensor"
//% blockNamespace=input
//% weight=65 blockGap=8
//% group="Color Sensor"
ambientLight() {
this.setMode(ColorSensorMode.Ambient)
return this.getNumber(NumberFormat.UInt8LE, 0)
}
getReflectedLight() {
/**
* Get current reflected light value from the color sensor.
* @param color the color sensor to query the request
*/
//% help=input/color/refelected-light
//% block="%color| reflected light"
//% blockId=colorGetReflected
//% parts="colorsensor"
//% blockNamespace=input
//% weight=64 blockGap=8
//% group="Color Sensor"
reflectedLight(): number {
this.setMode(ColorSensorMode.Reflect)
return this.getNumber(NumberFormat.UInt8LE, 0)
}
getColor(): ColorSensorColor {
/**
* Get the current color from the color sensor.
* @param color the color sensor to query the request
*/
//% help=input/color/color
//% block="%color| color"
//% blockId=colorGetColor
//% parts="colorsensor"
//% blockNamespace=input
//% weight=66 blockGap=8
//% group="Color Sensor"
color(): ColorSensorColor {
this.setMode(ColorSensorMode.Color)
return this.getNumber(NumberFormat.UInt8LE, 0)
}
}
//% whenUsed
export const color: ColorSensor = new ColorSensor()
//% whenUsed block="color sensor 3" weight=95 fixedInstance
export const color3: ColorSensor = new ColorSensor(3)
//% whenUsed block="color sensor 1" weight=95 fixedInstance
export const color1: ColorSensor = new ColorSensor(1)
//% whenUsed block="color sensor 2" weight=95 fixedInstance
export const color2: ColorSensor = new ColorSensor(2)
//% whenUsed block="color sensor 4" weight=95 fixedInstance
export const color4: ColorSensor = new ColorSensor(4)
}

View File

@ -5,9 +5,10 @@ const enum GyroSensorMode {
}
namespace input {
//% fixedInstances
export class GyroSensor extends internal.UartSensor {
constructor() {
super()
constructor(port: number) {
super(port)
}
_deviceType() {
@ -18,17 +19,48 @@ namespace input {
this._setMode(m)
}
getAngle() {
/**
* Get the current angle from the gyroscope.
* @param sensor the gyroscope to query the request
*/
//% help=input/gyro/angle
//% block="%sensor|angle"
//% blockId=gyroGetAngle
//% parts="gyroscope"
//% blockNamespace=input
//% weight=65 blockGap=8
//% group="Gyro Sensor"
angle() {
this.setMode(GyroSensorMode.Angle)
return this.getNumber(NumberFormat.Int16LE, 0)
}
getRate() {
/**
* Get the current rotation rate from the gyroscope.
* @param sensor the gyroscope to query the request
*/
//% help=input/gyro/rate
//% block="%sensor|rotation rate"
//% blockId=gyroGetRate
//% parts="gyroscope"
//% blockNamespace=input
//% weight=65 blockGap=8
//% group="Gyro Sensor"
rate() {
this.setMode(GyroSensorMode.Rate)
return this.getNumber(NumberFormat.Int16LE, 0)
}
}
//% whenUsed
export const gyro: GyroSensor = new GyroSensor()
//% fixedInstance whenUsed block="gyro sensor 2"
export const gyro2: GyroSensor = new GyroSensor(2)
//% fixedInstance whenUsed block="gyro sensor 1"
export const gyro1: GyroSensor = new GyroSensor(1)
//% fixedInstance whenUsed block="gyro sensor 3"
export const gyro3: GyroSensor = new GyroSensor(3)
//% fixedInstance whenUsed block="gyro sensor 4"
export const gyro4: GyroSensor = new GyroSensor(4)
}

View File

@ -27,30 +27,27 @@ namespace input.internal {
let analogMM: MMap
let uartMM: MMap
let devcon: Buffer
let sensors: SensorInfo[]
let autoSensors: Sensor[]
let sensorInfos: SensorInfo[]
class SensorInfo {
port: number
sensor: Sensor
sensors: Sensor[]
connType: number
devType: number
manual: boolean
constructor(p: number) {
this.port = p
this.connType = DAL.CONN_NONE
this.devType = DAL.DEVICE_TYPE_NONE
this.sensor = null
this.manual = false
this.sensors = []
}
}
function init() {
if (sensors) return
sensors = []
for (let i = 0; i < DAL.NUM_INPUTS; ++i) sensors.push(new SensorInfo(i))
autoSensors = []
if (sensorInfos) return
sensorInfos = []
for (let i = 0; i < DAL.NUM_INPUTS; ++i) sensorInfos.push(new SensorInfo(i))
devcon = output.createBuffer(DevConOff.Size)
analogMM = control.mmap("/dev/lms_analog", AnalogOff.Size, 0)
@ -64,7 +61,7 @@ namespace input.internal {
loops.pause(500)
})
for (let info_ of sensors) {
for (let info_ of sensorInfos) {
let info = info_
unsafePollForChanges(50, () => {
if (info.sensor) return info.sensor._query()
@ -90,7 +87,7 @@ namespace input.internal {
let conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
let numChanged = 0
for (let info of sensors) {
for (let info of sensorInfos) {
let newConn = conns[info.port]
if (newConn == info.connType)
continue
@ -117,77 +114,44 @@ namespace input.internal {
if (numChanged == 0)
return
let autos = sensors.filter(s => !s.manual)
// first free up disconnected sensors
for (let info of autos) {
if (info.sensor && info.devType == DAL.DEVICE_TYPE_NONE)
info.sensor._setPort(0)
}
for (let info of autos) {
if (!info.sensor && info.devType != DAL.DEVICE_TYPE_NONE) {
let found = false
for (let s of autoSensors) {
if (s.getPort() == 0 && s._deviceType() == info.devType) {
s._setPort(info.port + 1)
found = true
break
}
for (let si of sensorInfos) {
if (si.sensor && si.sensor._deviceType() != si.devType) {
si.sensor = null
}
if (si.devType != DAL.DEVICE_TYPE_NONE) {
// TODO figure out compiler problem when '|| null' is added here!
si.sensor = si.sensors.filter(s => s._deviceType() == si.devType)[0]
if (si.sensor == null) {
control.dmesg(`sensor not found for type=${si.devType} at ${si.port}`)
} else {
control.dmesg(`sensor connected type=${si.devType} at ${si.port}`)
si.sensor._activated()
}
if (!found)
control.dmesg(`sensor not found for type=${info.devType} at ${info.port}`)
}
}
}
export class Sensor extends control.Component {
protected port: number
protected port: number // this is 0-based
constructor() {
constructor(port_: number) {
super()
if (!(1 <= port_ && port_ <= DAL.NUM_INPUTS))
control.panic(120)
this.port = port_ - 1
init()
this.port = -1
let tp = this._deviceType()
if (autoSensors.filter(s => s._deviceType() == tp).length == 0) {
autoSensors.push(this)
}
sensorInfos[this.port].sensors.push(this)
}
// 0 - disable, 1-4 port number
_setPort(port: number, manual = false) {
port = Math.clamp(0, 4, port | 0) - 1;
if (port == this.port) return
this.port = port
control.dmesg(`sensor set port ${port} on devtype=${this._deviceType()}`)
for (let i = 0; i < sensors.length; ++i) {
if (i != this.port && sensors[i].sensor == this) {
sensors[i].sensor = null
sensors[i].manual = false
}
}
if (this.port >= 0) {
let prev = sensors[this.port].sensor
if (prev && prev != this)
prev._setPort(0)
sensors[this.port].sensor = this
sensors[this.port].manual = manual
}
this._portUpdated()
}
protected _portUpdated() { }
setPort(port: number) {
this._setPort(port, true)
}
_activated() { }
// 1-based
getPort() {
return this.port + 1
}
isManual() {
return this.port >= 0 && sensors[this.port].manual
isActive() {
return sensorInfos[this.port].sensor == this
}
_query() {
@ -203,12 +167,12 @@ namespace input.internal {
}
export class AnalogSensor extends Sensor {
constructor() {
super()
constructor(port: number) {
super(port)
}
_readPin6() {
if (this.port < 0) return 0
if (!this.isActive()) return 0
return analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.InPin6 + 2 * this.port)
}
}
@ -216,32 +180,26 @@ namespace input.internal {
export class UartSensor extends Sensor {
protected mode: number
protected realmode: number
protected mode: number // the mode user asked for
protected realmode: number // the mode the hardware is in
constructor() {
super()
constructor(port: number) {
super(port)
this.mode = 0
this.realmode = -1
}
protected _portUpdated() {
this.realmode = -1
if (this.port >= 0) {
if (this.isManual()) {
uartReset(this.port)
} else {
this.realmode = 0
}
this._setMode(this.mode)
}
_activated() {
this.realmode = 0
// uartReset(this.port) // TODO is it ever needed?
this._setMode(this.mode)
}
protected _setMode(m: number) {
//control.dmesg(`_setMode p=${this.port} m: ${this.realmode} -> ${m}`)
let v = m | 0
this.mode = v
if (this.port < 0) return
if (!this.isActive()) return
if (this.realmode != this.mode) {
this.realmode = v
setUartMode(this.port, v)
@ -249,10 +207,12 @@ namespace input.internal {
}
getBytes(): Buffer {
return getUartBytes(this.port)
return getUartBytes(this.isActive() ? this.port : -1)
}
getNumber(fmt: NumberFormat, off: number) {
if (!this.isActive())
return 0
return getUartNumber(fmt, off, this.port)
}
}

View File

@ -40,41 +40,130 @@ namespace input {
}
}
export class IrSensor extends internal.UartSensor {
private channel: IrRemoteChannel
private buttons: Button[];
let buttons: RemoteInfraredBeaconButton[]
constructor() {
super()
this.channel = IrRemoteChannel.Ch0
this.buttons = []
// otherwise button events won't work
this.mode = IrSensorMode.RemoteControl
function create(ir: InfraredSensor) {
// it's created by referencing it
}
export function irButton(id: IrRemoteButton): RemoteInfraredBeaconButton {
if (buttons == null) {
buttons = []
for (let i = 0; i < 5; ++i) {
this.buttons.push(new Button())
buttons.push(new RemoteInfraredBeaconButton(new Button()))
}
// make sure sensors are up
create(infraredSensor1)
create(infraredSensor2)
create(infraredSensor3)
create(infraredSensor4)
}
button(id: IrRemoteButton) {
let num = -1
while (id) {
id >>= 1;
num++;
}
num = Math.clamp(0, this.buttons.length - 1, num)
return this.buttons[num]
let num = -1
while (id) {
id >>= 1;
num++;
}
num = Math.clamp(0, buttons.length - 1, num)
return buttons[num]
}
//% fixedInstances
export class RemoteInfraredBeaconButton extends control.Component {
private button: Button;
constructor(button: Button) {
super();
this.button = button;
}
_update(curr: boolean) {
this.button._update(curr);
}
/**
* Check if a remote button is currently pressed or not.
* @param button the remote button to query the request
*/
//% help=input/remote-infrared-beacon/is-pressed
//% block="%button|is pressed"
//% blockId=remoteButtonIsPressed
//% parts="remote"
//% blockNamespace=input
//% weight=81 blockGap=8
//% group="Remote Infrared Beacon"
isPressed() {
return this.button.isPressed();
}
/**
* See if the remote button was pressed again since the last time you checked.
* @param button the remote button to query the request
*/
//% help=input/remote-infrared-beacon/was-pressed
//% block="%button|was pressed"
//% blockId=remotebuttonWasPressed
//% parts="remote"
//% blockNamespace=input
//% weight=80 blockGap=8
//% group="Remote Infrared Beacon"
wasPressed() {
return this.button.wasPressed();
}
/**
* Do something when a button or sensor is clicked, up or down
* @param button the button that needs to be clicked or used
* @param event the kind of button gesture that needs to be detected
* @param body code to run when the event is raised
*/
//% help=input/remote-infrared-beacon/on-event
//% blockId=remotebuttonEvent block="on %button|%event"
//% parts="remote"
//% blockNamespace=input
//% weight=99 blockGap=8
//% group="Remote Infrared Beacon"
onEvent(ev: ButtonEvent, body: () => void) {
this.button.onEvent(ev, body);
}
}
//% fixedInstances
export class InfraredSensor extends internal.UartSensor {
private channel: IrRemoteChannel;
private proximityThreshold: number;
constructor(port: number) {
super(port)
this.channel = IrRemoteChannel.Ch0
this.proximityThreshold = 10;
irButton(0) // make sure buttons array is initalized
// and set the mode, as otherwise button events won't work
this.mode = IrSensorMode.RemoteControl;
}
_query() {
if (this.mode == IrSensorMode.RemoteControl)
return mapButton(this.getNumber(NumberFormat.UInt8LE, this.channel))
return mapButton(this.getNumber(NumberFormat.UInt8LE, this.channel));
else if (this.mode == IrSensorMode.Proximity) {
const d = this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff;
return d < this.proximityThreshold ? PromixityEvent.ObjectNear
: d > this.proximityThreshold + 5 ? PromixityEvent.ObjectDetected
: 0;
}
return 0
}
_update(prev: number, curr: number) {
for (let i = 0; i < this.buttons.length; ++i) {
let v = !!(curr & (1 << i))
this.buttons[i].update(v)
if (this.mode == IrSensorMode.RemoteControl) {
for (let i = 0; i < buttons.length; ++i) {
let v = !!(curr & (1 << i))
buttons[i]._update(v)
}
} else {
if (curr)
control.raiseEvent(this._id, curr);
}
}
@ -85,59 +174,113 @@ namespace input {
setRemoteChannel(c: IrRemoteChannel) {
c = Math.clamp(0, 3, c | 0)
this.channel = c
this.setMode(IrSensorMode.RemoteControl)
this._setMode(IrSensorMode.RemoteControl)
}
setMode(m: IrSensorMode) {
this._setMode(m)
}
getDistance() {
this.setMode(IrSensorMode.Proximity)
/**
* Registers code to run when an object is getting near.
* @param handler the code to run when detected
*/
//% help=input/infrared/on-object-near
//% block="on %sensor|object near"
//% blockId=infraredOnObjectNear
//% parts="infraredsensor"
//% blockNamespace=input
//% weight=100 blockGap=8
//% group="Infrared Sensor"
onObjectNear(handler: () => void) {
control.onEvent(this._id, PromixityEvent.ObjectNear, handler);
if (this.proximity() == PromixityEvent.ObjectNear)
control.runInBackground(handler);
}
setObjectNearThreshold(distance: number) {
this.proximityThreshold = Math.max(1, Math.min(95, distance));
}
/**
* Get the promixity measured by the infrared sensor, from ``0`` (close) to ``100`` (far)
* @param ir the infrared sensor
*/
//% help=input/infrared/proximity
//% block="%infrared|proximity"
//% blockId=infraredGetProximity
//% parts="infrared"
//% blockNamespace=input
//% weight=65 blockGap=8
//% group="Infrared Sensor"
proximity() {
this._setMode(IrSensorMode.Proximity)
return this.getNumber(NumberFormat.UInt8LE, 0)
}
getRemoteCommand() {
this.setMode(IrSensorMode.RemoteControl)
/**
* Get the remote commandreceived the infrared sensor.
* @param ir the infrared sensor
*/
//% help=input/infrared/remote-command
//% block="%infrared|remote command"
//% blockId=infraredGetRemoteCommand
//% parts="infrared"
//% blockNamespace=input
//% weight=65 blockGap=8
//% group="Infrared Sensor"
remoteCommand() {
this._setMode(IrSensorMode.RemoteControl)
return this.getNumber(NumberFormat.UInt8LE, this.channel)
}
// TODO
getDirectionAndDistance() {
this.setMode(IrSensorMode.Seek)
this._setMode(IrSensorMode.Seek)
return this.getNumber(NumberFormat.UInt16LE, this.channel * 2)
}
}
//% whenUsed
export const ir: IrSensor = new IrSensor()
//% fixedInstance whenUsed block="infrared sensor 1"
export const infraredSensor1: InfraredSensor = new InfraredSensor(1)
/**
* Remote top-left button.
*/
//% whenUsed block="remote top-left" weight=95 fixedInstance
export const remoteTopLeft = ir.button(IrRemoteButton.TopLeft)
//% fixedInstance whenUsed block="infrared sensor 2"
export const infraredSensor2: InfraredSensor = new InfraredSensor(2)
/**
* Remote top-right button.
*/
//% whenUsed block="remote top-right" weight=95 fixedInstance
export const remoteTopRight = ir.button(IrRemoteButton.TopRight)
//% fixedInstance whenUsed block="infrared sensor 3"
export const infraredSensor3: InfraredSensor = new InfraredSensor(3)
/**
* Remote bottom-left button.
*/
//% whenUsed block="remote bottom-left" weight=95 fixedInstance
export const remoteBottomLeft = ir.button(IrRemoteButton.BottomLeft)
//% fixedInstance whenUsed block="infrared sensor 4"
export const infraredSensor4: InfraredSensor = new InfraredSensor(4)
/**
* Remote bottom-right button.
*/
//% whenUsed block="remote bottom-right" weight=95 fixedInstance
export const remoteBottomRight = ir.button(IrRemoteButton.BottomRight)
/**
* Remote beacon (center) button.
*/
//% whenUsed block="remote center" weight=95 fixedInstance
export const remoteCenter = ir.button(IrRemoteButton.CenterBeacon)
//% whenUsed block="remote button center" weight=95 fixedInstance
export const remoteButtonCenter = irButton(IrRemoteButton.CenterBeacon)
/**
* Remote top-left button.
*/
//% whenUsed block="remote button top-left" weight=95 fixedInstance
export const remoteButtonTopLeft = irButton(IrRemoteButton.TopLeft)
/**
* Remote top-right button.
*/
//% whenUsed block="remote button top-right" weight=95 fixedInstance
export const remoteButtonTopRight = irButton(IrRemoteButton.TopRight)
/**
* Remote bottom-left button.
*/
//% whenUsed block="remote button bottom-left" weight=95 fixedInstance
export const remoteButtonBottomLeft = irButton(IrRemoteButton.BottomLeft)
/**
* Remote bottom-right button.
*/
//% whenUsed block="remote button bottom-right" weight=95 fixedInstance
export const remoteButtonBottomRight = irButton(IrRemoteButton.BottomRight)
}

View File

@ -1,4 +1,5 @@
//% color="#B4009E" weight=98 icon="\uf192"
//% groups='["Brick", "Touch Sensor", "Color Sensor", "Ultrasonic Sensor", "Infrared Sensor", "Remote Infrared Beacon", "Gyro Sensor"]'
namespace input {
}

View File

@ -1,8 +1,13 @@
enum Output {
//% block="A"
A = 0x01,
//% block="B"
B = 0x02,
//% block="C"
C = 0x04,
//% block="D"
D = 0x08,
//% block="All"
ALL = 0x0f
}
@ -30,7 +35,7 @@ namespace output {
if (!pwmMM) control.fail("no PWM file")
motorMM = control.mmap("/dev/lms_motor", MotorDataOff.Size * DAL.NUM_OUTPUTS, 0)
stop(Output.ALL)
resetMotors()
let buf = output.createBuffer(1)
buf[0] = DAL.opProgramStart
@ -48,67 +53,173 @@ namespace output {
}
function mkCmd(out: Output, cmd: number, addSize: number) {
let b = createBuffer(2 + addSize)
const b = createBuffer(2 + addSize)
b.setNumber(NumberFormat.UInt8LE, 0, cmd)
b.setNumber(NumberFormat.UInt8LE, 1, out)
return b
}
/**
* Turn a motor on for a specified number of milliseconds.
* @param out the output connection that the motor is connected to
* @param ms the number of milliseconds to turn the motor on, eg: 500
* @param useBrake whether or not to use the brake, defaults to false
*/
//% blockId=output_turn block="turn motor %out| on for %ms|milliseconds"
//% weight=100 group="Motors"
export function turn(out: Output, ms: number, useBrake = false) {
// TODO: use current power / speed configuration
output.step(out, {
power: 100,
step1: 0,
step2: ms,
step3: 0,
useBrake: useBrake
})
function resetMotors() {
reset(Output.ALL)
}
/**
* Turn motor off.
* @param out the output connection that the motor is connected to
* Stops all motors
*/
//% blockId=output_stop block="turn motor %out|off"
//% weight=90 group="Motors"
export function stop(out: Output, useBrake = false) {
let b = mkCmd(out, DAL.opOutputStop, 1)
b.setNumber(NumberFormat.UInt8LE, 2, useBrake ? 1 : 0)
//% blockId=motorStopAll block="stop all motors"
//% weight=10 group="Motors" blockGap=8
export function stopAllMotors() {
const b = mkCmd(Output.ALL, DAL.opOutputStop, 0)
writePWM(b)
}
/**
* Turn motor on.
* @param out the output connection that the motor is connected to
*/
//% blockId=output_start block="turn motor %out|on"
//% weight=95 group="Motors"
export function start(out: Output) {
let b = mkCmd(out, DAL.opOutputStart, 0)
writePWM(b)
}
//% fixedInstances
export class Motor extends control.Component {
private port: Output;
private large: boolean;
private brake: boolean;
export function reset(out: Output) {
let b = mkCmd(out, DAL.opOutputReset, 0)
writePWM(b)
}
constructor(port: Output, large: boolean) {
super();
this.port = port;
this.large = large;
this.brake = false;
}
export function clearCount(out: Output) {
let b = mkCmd(out, DAL.opOutputClearCount, 0)
writePWM(b)
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
if (out & (1 << i)) {
motorMM.setNumber(NumberFormat.Int32LE, i * MotorDataOff.Size + MotorDataOff.TachoSensor, 0)
/**
* Power on or off the motor.
* @param motor the motor to turn on
* @param power the motor power level from ``-100`` to ``100``, eg: 50
*/
//% blockId=outputMotorOn block="%motor|%onOrOff"
//% onOrOff.fieldEditor=toggleonoff
//% weight=99 group="Motors" blockGap=8
on(onOrOff: boolean = true) {
if (onOrOff) {
const b = mkCmd(this.port, DAL.opOutputStart, 0)
writePWM(b);
} else {
const b = mkCmd(this.port, DAL.opOutputStop, 1)
b.setNumber(NumberFormat.UInt8LE, 2, this.brake ? 1 : 0)
writePWM(b)
}
}
/**
* Sets the motor power level from ``-100`` to ``100``.
* @param motor the output connection that the motor is connected to
* @param power the desired speed to use. eg: 50
*/
//% blockId=motorSetPower block="%motor|set power to %speed"
//% weight=62 group="Motors" blockGap=8
//% speed.min=-100 speed.max=100
setPower(power: number) {
const b = mkCmd(this.port, DAL.opOutputPower, 1)
b.setNumber(NumberFormat.Int8LE, 2, Math.clamp(-100, 100, power))
writePWM(b)
}
/**
* Sets the automatic brake on or off when the motor is off
* @param brake a value indicating if the motor should break when off
*/
//% blockId=outputMotorSetBrakeMode block="%motor|set brake %brake"
//% brake.fieldEditor=toggleonoff
//% weight=60 group="Motors" blockGap=8
setBrake(brake: boolean) {
this.brake = brake;
}
/**
* Reverses the motor polarity
*/
//% blockId=motorSetReversed block="%motor|set reversed %reversed"
//% reversed.fieldEditor=toggleonoff
//% weight=59 group="Motors"
setReversed(reversed: boolean) {
const b = mkCmd(this.port, DAL.opOutputPolarity, 1)
b.setNumber(NumberFormat.Int8LE, 2, reversed ? -1 : 1);
writePWM(b)
}
/**
* Gets motor actual speed.
* @param motor the port which connects to the motor
*/
//% blockId=motorSpeed block="%motor|speed"
//% weight=50 group="Motors" blockGap=8
speed(): number {
return getMotorData(this.port).actualSpeed;
}
/**
* Gets motor step count.
* @param motor the port which connects to the motor
*/
//% blockId=motorCount block="%motor|count"
//% weight=49 group="Motors" blockGap=8
count(): number {
return getMotorData(this.port).count;
}
/**
* Gets motor tacho count.
* @param motor the port which connects to the motor
*/
//% blockId=motorTachoCount block="%motor|tacho count"
//% weight=48 group="Motors"
tachoCount(): number {
return getMotorData(this.port).tachoCount;
}
/**
* Clears the motor count
*/
clearCount() {
const b = mkCmd(this.port, DAL.opOutputClearCount, 0)
writePWM(b)
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
if (this.port & (1 << i)) {
motorMM.setNumber(NumberFormat.Int32LE, i * MotorDataOff.Size + MotorDataOff.TachoSensor, 0)
}
}
}
/**
* Resets the motor.
*/
reset() {
reset(this.port);
}
}
//% whenUsed fixedInstance block="large motor A"
export const largeMotorA = new Motor(Output.A, true);
//% whenUsed fixedInstance block="large motor B"
export const largeMotorB = new Motor(Output.B, true);
//% whenUsed fixedInstance block="large motor C"
export const largeMotorC = new Motor(Output.C, true);
//% whenUsed fixedInstance block="large motor D"
export const largeMotorD = new Motor(Output.D, true);
//% whenUsed fixedInstance block="medium motor A"
export const mediumMotorA = new Motor(Output.A, false);
//% whenUsed fixedInstance block="medium motor B"
export const mediumMotorB = new Motor(Output.B, false);
//% whenUsed fixedInstance block="medium motor C"
export const mediumMotorC = new Motor(Output.C, false);
//% whenUsed fixedInstance block="medium motor D"
export const mediumMotorD = new Motor(Output.D, false);
function reset(out: Output) {
let b = mkCmd(out, DAL.opOutputReset, 0)
writePWM(b)
}
function outOffset(out: Output) {
@ -119,14 +230,14 @@ namespace output {
return 0
}
export interface MotorData {
interface MotorData {
actualSpeed: number; // -100..+100
tachoCount: number;
count: number;
}
// only a single output at a time
export function getMotorData(out: Output): MotorData {
function getMotorData(out: Output): MotorData {
let buf = motorMM.slice(outOffset(out), MotorDataOff.Size)
return {
actualSpeed: buf.getNumber(NumberFormat.Int8LE, MotorDataOff.Speed),
@ -135,51 +246,7 @@ namespace output {
}
}
/**
* Get motor speed.
* @param out the output connection that the motor is connected to
*/
//% blockId=output_getCurrentSpeed block="motor %out|speed"
//% weight=70 group="Motors"
export function getCurrentSpeed(out: Output) {
return getMotorData(out).actualSpeed;
}
/**
* Set motor speed.
* @param out the output connection that the motor is connected to
* @param speed the desired speed to use. eg: 100
*/
//% blockId=output_setSpeed block="set motor %out| speed to %speed"
//% weight=81 group="Motors"
//% speed.min=-100 speed.max=100
export function setSpeed(out: Output, speed: number) {
let b = mkCmd(out, DAL.opOutputSpeed, 1)
b.setNumber(NumberFormat.Int8LE, 2, Math.clamp(-100, 100, speed))
writePWM(b)
}
/**
* Set motor power.
* @param out the output connection that the motor is connected to
* @param power the desired power to use. eg: 100
*/
//% blockId=output_setPower block="set motor %out| power to %power"
//% weight=80 group="Motors"
//% power.min=-100 power.max=100
export function setPower(out: Output, power: number) {
let b = mkCmd(out, DAL.opOutputPower, 1)
b.setNumber(NumberFormat.Int8LE, 2, Math.clamp(-100, 100, power))
writePWM(b)
}
export function setPolarity(out: Output, polarity: number) {
let b = mkCmd(out, DAL.opOutputPolarity, 1)
b.setNumber(NumberFormat.Int8LE, 2, Math.clamp(-1, 1, polarity))
writePWM(b)
}
export interface StepOptions {
interface StepOptions {
power?: number;
speed?: number; // either speed or power has to be present
step1: number;
@ -189,7 +256,7 @@ namespace output {
useBrake?: boolean;
}
export function step(out: Output, opts: StepOptions) {
function step(out: Output, opts: StepOptions) {
let op = opts.useSteps ? DAL.opOutputStepSpeed : DAL.opOutputTimeSpeed
let speed = opts.speed
if (speed == null) {

View File

@ -78,13 +78,21 @@ namespace screen {
}
}
export function setPixel(x: number, y: number, mode = Draw.Normal) {
/**
* Sets a pixel on or off
* @param on a value indicating if the pixel should be on or off
* @param x the starting position's x coordinate, eg: 0
* @param y the starting position's x coordinate, eg: 0
*/
//% blockId=screen_setpixel block="set pixel %on| at x: %x| y: %y"
//% weight=98 group="Brick" blockNamespace=output
//% x.min=0 x.max=178 y.min=0 y.max=128 on.fieldEditor=toggleonoff
export function setPixel(on: boolean, x: number, y: number) {
x |= 0
y |= 0
if (0 <= x && x < DAL.LCD_WIDTH && 0 <= y && y < DAL.LCD_HEIGHT)
_setPixel(x, y, mode)
_setPixel(x, y, on ? Draw.Normal : Draw.Clear)
}
/**
* Show text on the screen.
@ -92,9 +100,10 @@ namespace screen {
* @param x the starting position's x coordinate, eg: 0
* @param y the starting position's x coordinate, eg: 0
*/
//% blockId=screen_drawText block="print %text| at x: %x| y: %y"
//% weight=99 group="Screen" blockNamespace=output inlineInputMode="inline"
export function drawText(text: string, x: number, y: number, mode = Draw.Normal) {
//% blockId=screen_print block="print %text| at x: %x| y: %y"
//% weight=99 group="Brick" blockNamespace=output inlineInputMode="inline"
//% x.min=0 x.max=178 y.min=0 y.max=128
export function print(text: string, x: number, y: number, mode = Draw.Normal) {
x |= 0
y |= 0
if (!currFont) currFont = defaultFont()

View File

@ -1,8 +1,8 @@
screen.clear()
screen.drawText("PXT!", 10, 30, Draw.Quad)
screen.print("PXT!", 10, 30, Draw.Quad)
screen.drawRect(40, 40, 20, 10, Draw.Fill)
output.setLights(LightsPattern.Orange)
output.setStatusLight(LightsPattern.Orange)
screen.drawIcon(100, 50, screen.doubleIcon(screen.heart), Draw.Double | Draw.Transparent)
@ -12,37 +12,37 @@ input.buttonEnter.onEvent(ButtonEvent.Click, () => {
input.buttonLeft.onEvent(ButtonEvent.Click, () => {
screen.drawRect(10, 70, 20, 10, Draw.Fill)
output.setLights(LightsPattern.Red)
output.setStatusLight(LightsPattern.Red)
screen.setFont(screen.microbitFont())
})
input.buttonRight.onEvent(ButtonEvent.Click, () => {
screen.drawText("Right!", 10, 60)
screen.print("Right!", 10, 60)
})
input.buttonDown.onEvent(ButtonEvent.Click, () => {
screen.drawText("Down! ", 10, 60)
screen.print("Down! ", 10, 60)
})
input.buttonUp.onEvent(ButtonEvent.Click, () => {
screen.drawText("Up! ", 10, 60)
screen.print("Up! ", 10, 60)
})
let num = 0
input.touchSensor.onEvent(ButtonEvent.Click, () => {
screen.drawText("Click! " + num, 10, 60)
input.touchSensor1.onEvent(TouchSensorEvent.Bumped, () => {
screen.print("Click! " + num, 10, 60)
num++
})
input.remoteTopLeft.onEvent(ButtonEvent.Click, () => {
screen.drawText("TOPLEFT " + num, 10, 60)
input.remoteButtonTopLeft.onEvent(ButtonEvent.Click, () => {
screen.print("TOPLEFT " + num, 10, 60)
num++
})
input.remoteTopRight.onEvent(ButtonEvent.Down, () => {
screen.drawText("TOPRIGH " + num, 10, 60)
input.remoteButtonTopRight.onEvent(ButtonEvent.Down, () => {
screen.print("TOPRIGH " + num, 10, 60)
num++
})
@ -54,7 +54,7 @@ loops.forever(() => {
/*
loops.forever(() => {
let v = input.color.getColor()
screen.drawText(10, 60, v + " ")
screen.print(10, 60, v + " ")
loops.pause(200)
})
*/
*/

View File

@ -1,10 +1,26 @@
namespace input {
export class TouchSensor extends internal.AnalogSensor {
button: Button;
// keep TouchSensorEvent in sync with ButtonEvent
constructor() {
super()
this.button = new Button()
/**
* Touch sensor interactions
*/
const enum TouchSensorEvent {
//% block="pressed"
Pressed = 4,
//% block="bumped"
Bumped = 1,
//% block="released"
Released = 3,
}
namespace input {
//% fixedInstances
export class TouchSensor extends internal.AnalogSensor {
private button: Button;
constructor(port: number) {
super(port)
this.button = new Button();
}
_query() {
@ -12,17 +28,51 @@ namespace input {
}
_update(prev: number, curr: number) {
this.button.update(curr > 0)
this.button._update(curr > 0)
}
_deviceType() {
return DAL.DEVICE_TYPE_TOUCH
}
/**
* Check if touch sensor is touched.
* @param sensor the port to query the request
*/
//% help=input/touch/is-touched
//% block="%sensor|is touched"
//% blockId=touchIsTouched
//% parts="touch"
//% blockNamespace=input
//% weight=81 blockGap=8
//% group="Touch Sensor"
isTouched() {
return this.button.isPressed();
}
/**
* Do something when a touch sensor is touched...
* @param sensor the touch sensor that needs to be clicked or used
* @param event the kind of button gesture that needs to be detected
* @param body code to run when the event is raised
*/
//% help=input/touch/on-event
//% blockId=touchEvent block="on %sensor|%event"
//% parts="touch"
//% blockNamespace=input
//% weight=99 blockGap=8
//% group="Touch Sensor"
onEvent(ev: TouchSensorEvent, body: () => void) {
this.button.onEvent(<ButtonEvent><number>ev, body)
}
}
//% whenUsed
export const touchSensorImpl: TouchSensor = new TouchSensor()
//% whenUsed
export const touchSensor: Button = touchSensorImpl.button
//% whenUsed block="touch sensor 1" weight=95 fixedInstance
export const touchSensor1: TouchSensor = new TouchSensor(1)
//% whenUsed block="touch sensor 2" weight=95 fixedInstance
export const touchSensor2: TouchSensor = new TouchSensor(2)
//% whenUsed block="touch sensor 3" weight=95 fixedInstance
export const touchSensor3: TouchSensor = new TouchSensor(3)
//% whenUsed block="touch sensor 4" weight=95 fixedInstance
export const touchSensor4: TouchSensor = new TouchSensor(4)
}

View File

@ -1,22 +1,85 @@
const enum PromixityEvent {
//% block="object near"
ObjectNear = 1,
//% block="object detected"
ObjectDetected = 2
}
namespace input {
//% fixedInstances
export class UltraSonicSensor extends internal.UartSensor {
constructor() {
super()
private promixityThreshold: number;
constructor(port: number) {
super(port)
this.promixityThreshold = 10;
}
_deviceType() {
return DAL.DEVICE_TYPE_ULTRASONIC
}
/** Get distance in mm */
getDistance() {
_query(): number {
const d = this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff;
return d < this.promixityThreshold ? PromixityEvent.ObjectNear
: d > this.promixityThreshold + 5 ? PromixityEvent.ObjectDetected
: 0;
}
_update(prev: number, curr: number) {
if (curr)
control.raiseEvent(this._id, curr);
}
/**
* Registers code to run when the given color is close
* @param handler the code to run when detected
*/
//% help=input/ultrasonic/on-object-near
//% block="on %sensor|object near"
//% blockId=ultrasonicOnObjectClose
//% parts="infraredsensor"
//% blockNamespace=input
//% weight=100 blockGap=8
//% group="Ultrasonic Sensor"
onObjectNear(handler: () => void) {
control.onEvent(this._id, PromixityEvent.ObjectNear, handler);
if (this.distance() == PromixityEvent.ObjectNear)
control.runInBackground(handler);
}
setObjectNearThreshold(distance: number) {
this.promixityThreshold = Math.max(1, Math.min(250, distance));
}
/**
* Gets the distance from the sonar in millimeters
* @param sensor the ultrasonic sensor port
*/
//% help=input/ultrasonic/distance
//% block="%sensor|distance"
//% blockId=sonarGetDistance
//% parts="ultrasonic"
//% blockNamespace=input
//% weight=65 blockGap=8
//% group="Ultrasonic Sensor"
distance() {
// it supposedly also has an inch mode, but we stick to mm
this._setMode(0)
return this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff
return this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff;
}
}
//% whenUsed
export const ultrasonic: UltraSonicSensor = new UltraSonicSensor()
//% fixedInstance whenUsed block="ultrasonic sensor 4"
export const ultrasonic4: UltraSonicSensor = new UltraSonicSensor(4)
//% fixedInstance whenUsed block="ultrasonic sensor 1"
export const ultrasonic1: UltraSonicSensor = new UltraSonicSensor(1)
//% fixedInstance whenUsed block="ultrasonic sensor 2"
export const ultrasonic2: UltraSonicSensor = new UltraSonicSensor(2)
//% fixedInstance whenUsed block="ultrasonic sensor 3"
export const ultrasonic3: UltraSonicSensor = new UltraSonicSensor(3)
}

View File

@ -1,11 +1,10 @@
//% color="#D42878"
//% groups="['Brick buttons']"
namespace input {
}
//% color="#8AC044" weight=90 icon="\uf185"
//% groups="['Lights', 'Screen', Motors']"
//% groups='["Motors", "Brick"]'
namespace output {
}

View File

@ -8,15 +8,15 @@
"music.noteFrequency|param|name": "the note name, eg: Note.C",
"music.playSound": "Start playing a sound and don't wait for it to finish.\nNotes are expressed as a string of characters with this format: NOTE[octave][:duration]",
"music.playSoundUntilDone": "Play a sound and wait until the sound is done.\nNotes are expressed as a string of characters with this format: NOTE[octave][:duration]",
"music.playSoundUntilDone|param|sound": "the melody to play, eg: 'g5:1'",
"music.playSound|param|sound": "the melody to play, eg: 'g5:1'",
"music.playSoundUntilDone|param|sound": "the melody to play, eg: music.sounds(Sounds.PowerUp)",
"music.playSound|param|sound": "the melody to play, eg: music.sounds(Sounds.PowerUp)",
"music.playTone": "Play a tone through the speaker for some amount of time.",
"music.playTone|param|frequency": "pitch of the tone to play in Hertz (Hz)",
"music.playTone|param|ms": "tone duration in milliseconds (ms)",
"music.rest": "Rest, or play silence, for some time (in milleseconds).",
"music.rest|param|ms": "rest duration in milliseconds (ms)",
"music.rest|param|ms": "rest duration in milliseconds (ms), eg: 100",
"music.ringTone": "Play a tone.",
"music.ringTone|param|frequency": "pitch of the tone to play in Hertz (Hz)",
"music.ringTone|param|frequency": "pitch of the tone to play in Hertz (Hz), eg: Note.C",
"music.setTempo": "Set the tempo a number of beats per minute (bpm).",
"music.setTempo|param|bpm": "The new tempo in beats per minute, eg: 120",
"music.setVolume": "Set the output volume of the sound synthesizer.",

View File

@ -29,14 +29,14 @@
"Sounds.Siren|block": "siren",
"Sounds.Wawawawaa|block": "wawawawaa",
"music.beat|block": "%fraction|beat",
"music.changeTempoBy|block": "change tempo by (bpm)|%value",
"music.changeTempoBy|block": "change tempo by %value|(bpm)",
"music.noteFrequency|block": "%note",
"music.playSoundUntilDone|block": "play sound %sound=music_sounds|until done",
"music.playSound|block": "play sound %sound=music_sounds",
"music.playTone|block": "play tone|at %note=device_note|for %duration=device_beat",
"music.rest|block": "rest|for %duration=device_beat",
"music.ringTone|block": "ring tone|at %note=device_note",
"music.setTempo|block": "set tempo to (bpm)|%value",
"music.setTempo|block": "set tempo to %value|(bpm)",
"music.setVolume|block": "set volume %volume",
"music.sounds|block": "%name",
"music.stopAllSounds|block": "stop all sounds",

View File

@ -67,10 +67,11 @@ static void _playTone(uint16_t frequency, uint16_t duration, uint8_t volume)
* @param frequency pitch of the tone to play in Hertz (Hz)
* @param ms tone duration in milliseconds (ms)
*/
//% help=music/play-tone weight=90
//% help=music/play-tone
//% blockId=music_play_note block="play tone|at %note=device_note|for %duration=device_beat"
//% parts="headphone" async blockGap=8
//% parts="headphone" async
//% blockNamespace=music
//% weight=76 blockGap=8
void playTone(int frequency, int ms) {
if (frequency <= 0) {
_stopSound();

View File

@ -18,10 +18,11 @@ declare namespace music {
* @param frequency pitch of the tone to play in Hertz (Hz)
* @param ms tone duration in milliseconds (ms)
*/
//% help=music/play-tone weight=90
//% help=music/play-tone
//% blockId=music_play_note block="play tone|at %note=device_note|for %duration=device_beat"
//% parts="headphone" async blockGap=8
//% blockNamespace=music shim=music::playTone
//% parts="headphone" async
//% blockNamespace=music
//% weight=76 blockGap=8 shim=music::playTone
function playTone(frequency: int32, ms: int32): void;
}

View File

@ -1,6 +1,6 @@
{
"name": "pxt-ev3",
"version": "0.0.14",
"version": "0.0.26",
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
"private": true,
"keywords": [
@ -39,8 +39,8 @@
"semantic-ui-less": "^2.2.4"
},
"dependencies": {
"pxt-common-packages": "0.9.2",
"pxt-core": "2.0.10"
"pxt-common-packages": "0.11.7",
"pxt-core": "2.3.4"
},
"scripts": {
"test": "node node_modules/pxt-core/built/pxt.js travis"

View File

@ -68,10 +68,10 @@
"appTheme": {
"accentColor": "#0089BF",
"logoUrl": "https://lego.makecode.com",
"logo": "./static/logo.svg",
"docsLogo": "./static/logo.square.svg",
"portraitLogo": "./static/logo.square.svg",
"footerLogo": "./static/logo.square.svg",
"logo": "./static/lego_education_logo.png",
"docsLogo": "./static/lego-logo.svg",
"portraitLogo": "./static/lego-logo.svg",
"footerLogo": "./static/lego-logo.svg",
"cardLogo": "./static/icons/android-chrome-192x192.png",
"appLogo": "./static/icons/android-chrome-192x192.png",
"organization": "Microsoft MakeCode",
@ -89,10 +89,6 @@
"name": "About",
"path": "/about"
},
{
"name": "Examples",
"path": "#projects:Examples"
},
{
"name": "Blocks",
"path": "/blocks"
@ -104,22 +100,14 @@
{
"name": "Reference",
"path": "/reference"
},
{
"name": "Buy",
"path": "https://www.lego.com/en-us/mindstorms/products/mindstorms-ev3-31313"
}
],
"galleries": {
"Make": "projects",
"Examples": "examples"
},
"sideDoc": "tutorials/getting-started",
"showHomeScreen": true,
"homeScreenHero": "./static/hero.png",
"invertedMenu": false,
"invertedMonaco": false,
"monacoToolbox": true,
"invertedToolbox": true,
"exampleGallery": "examples",
"hasAudio": true,
"usbHelp": [],
"extendEditor": true,

157
scripts/rgf2png.js Executable file
View File

@ -0,0 +1,157 @@
#!/usr/bin/env node
const fs = require("fs")
const zlib = require("zlib")
function compressImg(fn) {
const rgf = fs.readFileSync(fn)
const width = rgf[0]
const height = rgf[1]
const expSz = ((width + 7) >> 3) * height + 2
console.log(`w=${width} h=${height} sz=${rgf.length} exp=${expSz}`)
let crcTable
function crc32(buf) {
if (!crcTable) {
crcTable = []
for (let i = 0; i < 256; i++) {
let curr = i;
for (let j = 0; j < 8; j++) {
if (curr & 1) {
curr = 0xedb88320 ^ (curr >>> 1);
} else {
curr = curr >>> 1;
}
}
crcTable[i] = curr
}
}
let crc = -1;
for (var i = 0; i < buf.length; i++) {
crc = crcTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
}
return (crc ^ -1) >>> 0;
}
/*
Width 4 bytes
Height 4 bytes
Bit depth 1 byte
Colour type 1 byte
Compression method 1 byte
Filter method 1 byte
Interlace method 1 byte
*/
const chunks = []
function addChunk(mark, addsize) {
const buf = Buffer.alloc(mark.length + addsize)
for (let i = 0; i < mark.length; ++i) {
buf[i] = mark.charCodeAt(i)
}
chunks.push(buf)
return buf
}
const hd = addChunk("IHDR", 4 + 4 + 5)
hd.writeInt32BE(width, 4)
hd.writeInt32BE(height, 8)
hd[12] = 1 // bit depth
hd[13] = 0 // color type - grayscale
hd[14] = 0 // compression - deflate
hd[15] = 0 // filter method
hd[16] = 0 // interlace method - no interlace
const scanlines = []
const scanlen = (width + 7) >> 3
let srcptr = 2
let srcmask = 0x01
for (let y = 0; y < height; ++y) {
const scan = Buffer.alloc(1 + scanlen)
scanlines.push(scan)
let dstptr = 1
let dstmask = 0x80
for (let x = 0; x < width; ++x) {
if (!(rgf[srcptr] & srcmask)) {
scan[dstptr] |= dstmask
}
dstmask >>= 1;
if (dstmask == 0) {
dstmask = 0x80
dstptr++
}
srcmask <<= 1;
if (srcmask > 0x80) {
srcmask = 0x01
srcptr++
}
}
if (srcmask != 0x01) {
srcmask = 0x01
srcptr++
}
if (false) {
// seems to increase file size
scan[0] = 1 // sub
let prev = 0
for (let i = 1; i < scan.length; ++i) {
let p = scan[i]
scan[i] = (p - prev) & 0xff
prev = p
}
}
}
const dat = zlib.deflateSync(Buffer.concat(scanlines), {
level: 9
})
const idat = addChunk("IDAT", dat.length)
dat.copy(idat, 4)
addChunk("IEND", 0)
const output = [new Buffer([137, 80, 78, 71, 13, 10, 26, 10])]
function intBuf(v) {
let b = new Buffer(4)
b.writeUInt32BE(v, 0)
return b
}
for (let ch of chunks) {
output.push(intBuf(ch.length - 4))
output.push(ch)
output.push(intBuf(crc32(ch)))
}
let outp = Buffer.concat(output)
return outp
}
let sz = 0
let bf
let out = {}
for (let i = 2; i < process.argv.length; ++i) {
let fn = process.argv[i]
let m = /([^\/]+\/[^/]+)\.rgf$/.exec(fn)
let bn = m[1]
bf = compressImg(fn)
out[bn] = "data:image/png;base64," + bf.toString("base64")
sz += bf.length
}
console.log("total " + sz)
fs.writeFileSync("out.json", JSON.stringify(out, null, 4))
fs.writeFileSync("out.png", bf)
//if (require("os").platform() == "darwin")
// require('child_process').execSync("afplay out.wav")
// TODO also play on Windows

46
scripts/rsf2wav.js Executable file
View File

@ -0,0 +1,46 @@
#!/usr/bin/env node
const fs = require("fs")
const rsf = fs.readFileSync(process.argv[2])
const fmt = rsf.readInt16BE(0) // 0x0100
if (fmt != 0x0100) {
throw new Error("Invalid input format: " + fmt)
}
const size = rsf.readInt16BE(2)
const samplerate = rsf.readInt16BE(4)
const repeat = rsf.readInt16BE(6)
const datasize = rsf.length - 8
const wavHd = new Buffer(44)
function writeMark(off, mark) {
for (let i = 0; i < mark.length; ++i) {
wavHd[off + i] = mark.charCodeAt(i)
}
}
writeMark(0, 'RIFF')
wavHd.writeInt32LE(datasize + 36, 4)
writeMark(8, 'WAVE')
writeMark(12, 'fmt ')
wavHd.writeInt32LE(16, 16) // fmt size
wavHd.writeInt16LE(1, 20) // PCM
wavHd.writeInt16LE(1, 22) // mono, 1ch
wavHd.writeInt32LE(samplerate, 24)
wavHd.writeInt32LE(samplerate, 28) // byterate
wavHd.writeInt16LE(1, 32) // block align
wavHd.writeInt16LE(8, 34) // bits per sample
writeMark(36, 'data')
wavHd.writeInt32LE(datasize, 40)
const wav = Buffer.concat([wavHd, rsf.slice(8)])
console.log("writing out.wav; " + samplerate + "Hz")
fs.writeFileSync("out.wav", wav)
if (require("os").platform() == "darwin")
require('child_process').execSync("afplay out.wav")
// TODO also play on Windows

View File

@ -25,7 +25,7 @@ namespace pxsim {
export class DalBoard extends CoreBoard implements
AccelerometerBoard,
CommonBoard,
LightBoard,
// LightBoard,
LightSensorBoard,
MicrophoneBoard,
MusicBoard,
@ -34,7 +34,7 @@ namespace pxsim {
InfraredBoard,
CapTouchBoard {
// state & update logic for component services
neopixelState: CommonNeoPixelState;
// neopixelState: CommonNeoPixelState;
buttonState: EV3ButtonState;
slideSwitchState: SlideSwitchState;
lightSensorState: AnalogSensorState;
@ -62,11 +62,12 @@ namespace pxsim {
this.builtinParts["buttons"] = this.buttonState = new EV3ButtonState();
this.builtinParts["light"] = this.lightState = new EV3LightState();
this.builtinParts["screen"] = this.screenState = new EV3ScreenState();
this.builtinParts["audio"] = this.audioState = new AudioState();
/*this.builtinParts["neopixel"] = this.neopixelState = new CommonNeoPixelState();
this.builtinParts["buttonpair"] = this.buttonState = new CommonButtonState();
this.builtinParts["switch"] = this.slideSwitchState = new SlideSwitchState();
this.builtinParts["audio"] = this.audioState = new AudioState();
this.builtinParts["lightsensor"] = this.lightSensorState = new AnalogSensorState(DAL.DEVICE_ID_LIGHT_SENSOR, 0, 255);
this.builtinParts["thermometer"] = this.thermometerState = new AnalogSensorState(DAL.DEVICE_ID_THERMOMETER, -5, 50);
this.builtinParts["soundsensor"] = this.microphoneState = new AnalogSensorState(DAL.DEVICE_ID_TOUCH_SENSOR + 1, 0, 255);
@ -174,9 +175,9 @@ namespace pxsim {
return svg.toDataUri(new XMLSerializer().serializeToString(this.view));
}
defaultNeopixelPin() {
return this.edgeConnectorState.getPin(CPlayPinName.D8);
}
//defaultNeopixelPin() {
// return this.edgeConnectorState.getPin(CPlayPinName.D8);
//}
getDefaultPitchPin() {
return this.edgeConnectorState.getPin(CPlayPinName.D6);

View File

@ -480,6 +480,7 @@ namespace pxsim.visuals {
this.screenCanvasCtx.putImageData(this.screenCanvasData, 0, 0);
}
/*
private updateNeoPixels() {
let state = this.board;
if (!state || !state.neopixelState) return;
@ -509,6 +510,7 @@ namespace pxsim.visuals {
if (p_inner) svg.filter(p_inner, `url(#neopixelglow)`);
}
}
*/
private updateSound() {
let state = this.board;

View File

@ -6,5 +6,8 @@
],
"approvedRepos": [
]
},
"galleries": {
"Maker Activities": "maker"
}
}

52
theme/blockly.less Normal file
View File

@ -0,0 +1,52 @@
@import 'themes/default/globals/site.variables';
@import 'themes/pxt/globals/site.variables';
@import 'site/globals/site.variables';
@import 'blockly-core';
/* Toolbox padding */
.blocklyToolboxDiv, .monacoToolboxDiv {
padding: 0.5rem;
-webkit-box-shadow: inset 0px 0px 0px 2px rgba(255,255,255,0.31);
-moz-box-shadow: inset 0px 0px 0px 2px rgba(255,255,255,0.31);
box-shadow: inset 0px 0px 0px 2px rgba(255,255,255,0.31);
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
}
div.blocklyTreeRow {
border-radius: 0px;
-webkit-box-shadow: inset 0px 0px 0px 3px rgba(0,0,0,0.1);
-moz-box-shadow: inset 0px 0px 0px 3px rgba(0,0,0,0.1);
box-shadow: inset 0px 0px 0px 3px rgba(0,0,0,0.1);
}
/* Remove shadow around blockly blocks */
.blocklyPathDark, .blocklyPathLight {
display: none;
}
/* Blockly Text */
span.blocklyTreeLabel {
font-family: @pageFont !important;
text-transform: uppercase !important;
font-size:1rem !important;
font-weight: bold;
}
/* Search box */
#blocklySearchArea {
margin: 0.5rem;
margin-left: 1rem;
margin-right: 1rem;
}
.blocklySearchInputField {
border-radius: 1rem !important;
}
/* Mobile */
@media only screen and (max-width: @largestMobileScreen) {
#blocklyTrashIcon {
margin: 0.2rem;
}
}

View File

@ -22,7 +22,7 @@
/* Lego colors */
@red: @brightRed;
@blue: #008ad2;
@blue: #00a5c8; /*#008ad2;*/
@yellow: #fccd00;
@orange: #fa7f2a;
@green: @brightYellowishGreen;
@ -96,9 +96,11 @@
Menu
--------------------*/
@mainMenuBackground: #f4f7f9;
@mainMenuInvertedBackground: @yellow;
@mainMenuTutorialBackground: @orange;
@tutorialSelectedMenuColor: @blue;
/*-------------------
@ -117,6 +119,8 @@
@editorToolsBackground: #fcfbfa;
@blocklySvgColor: #ecf6ff;
@homeScreenBackground: #EAEEEF;
/*-------------------
Full screen
--------------------*/
@ -152,3 +156,13 @@
@blocklyRowHeightComputer: 50px;
@blocklyRowHeightTablet: 50px;
@blocklyRowHeightMobile: 50px;
/*-------------------
Flyout
--------------------*/
@flyoutLabelColor: white;
@blocklyFlyoutColor: #282828;
@blocklyFlyoutColorOpacity: 0.9;
@monacoFlyoutColor: rgba(40, 40, 40,0.9);

View File

@ -44,7 +44,7 @@
/* Menu bar colors */
#menubar .ui.item {
color: @red;
color: #373737;
}
.fullscreensim #menubar .ui.menu {
box-shadow: none !important;
@ -56,60 +56,19 @@
min-width: 2.0rem;
}
/* Toolbox padding */
.blocklyToolboxDiv, .monacoToolboxDiv {
padding: 0.5rem;
-webkit-box-shadow: inset 0px 0px 0px 2px rgba(255,255,255,0.31);
-moz-box-shadow: inset 0px 0px 0px 2px rgba(255,255,255,0.31);
box-shadow: inset 0px 0px 0px 2px rgba(255,255,255,0.31);
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
}
div.blocklyTreeRow {
border-radius: 0px;
-webkit-box-shadow: inset 0px 0px 0px 3px rgba(0,0,0,0.1);
-moz-box-shadow: inset 0px 0px 0px 3px rgba(0,0,0,0.1);
box-shadow: inset 0px 0px 0px 3px rgba(0,0,0,0.1);
}
/* Remove shadow around blockly blocks */
.blocklyPathDark, .blocklyPathLight {
display: none;
}
/* Blockly Text */
span.blocklyTreeLabel {
font-family: @pageFont !important;
text-transform: uppercase !important;
font-size:1rem !important;
font-weight: bold;
}
.blocklyFlyoutBackground {
fill: #282828 !important;
}
.monacoFlyout {
background: rgba(40, 40, 40, 0.9);
}
/* Editor menu toggle */
#menubar .ui.menu.fixed .item.editor-menuitem .ui.grid {
background: @blue !important;
border-radius: 0px !important;
}
#menubar .ui.menu.fixed .ui.item.editor-menuitem .item:not(.active) {
color: white;
}
/* Search box */
#blocklySearchArea {
margin: 0.5rem;
margin-left: 1rem;
margin-right: 1rem;
#menubar .ui.menu.fixed .ui.item.editor-menuitem .item {
border-radius: 0px !important;
}
.blocklySearchInputField {
border-radius: 1rem !important;
#menubar .ui.menu.fixed .ui.item.editor-menuitem .item.active {
color: @blue;
}
.sandboxfooter a:not(.thin) {
@ -121,9 +80,6 @@ span.blocklyTreeLabel {
#filelist {
background: transparent;
}
#blocklyTrashIcon {
margin: 0.2rem;
}
}
/* Tablet */

View File

@ -49,10 +49,10 @@
/* Modules */
@accordion : 'default';
@checkbox : 'default';
@dimmer : 'default';
@dimmer : 'pxt';
@dropdown : 'default';
@embed : 'default';
@modal : 'default';
@modal : 'pxt';
@nag : 'default';
@popup : 'default';
@progress : 'default';
@ -66,7 +66,7 @@
/* Views */
@ad : 'default';
@card : 'default';
@card : 'pxt';
@comment : 'default';
@feed : 'default';
@item : 'default';