Compare commits

...

26 Commits

Author SHA1 Message Date
348964c888 1.1.10 2019-08-28 22:43:42 -07:00
8b3461bebd Add exitThread() polling the exit button (#888)
* Add exitThread() polling the exit button

* Add missing includes

* Remove redundant code
2019-08-28 22:43:21 -07:00
e511630c2e Update README.md 2019-08-28 16:27:03 -07:00
db156d5df0 Update README.md 2019-08-28 16:24:55 -07:00
93c6975400 1.1.9 2019-08-28 16:21:41 -07:00
abc93dd7da Multi sensor fix (#887)
* more logging

* set uart mode all at once

* updated logging

* pr feedback
2019-08-28 16:21:06 -07:00
85cfc86bf8 1.1.8 2019-08-28 13:36:50 -07:00
b66d4f2d64 enable storage extension (#886)
* enable storage extension

* fix -beta
2019-08-28 13:36:23 -07:00
5843deab11 1.1.7 2019-08-28 11:39:18 -07:00
8d5edc38bb bump common version (#885) 2019-08-28 11:30:59 -07:00
0309e50058 1.1.6 2019-08-28 08:52:24 -07:00
aa40e7b169 Endprogram (#884)
* moving end program logic to c++

* typo

* always stop on reset
2019-08-28 08:52:01 -07:00
75cf8da396 1.1.5 2019-08-27 17:57:44 -07:00
Max
db9b6a995b IIC added (#870)
* IIC added

* Fixed bug with not detecting device
2019-08-27 17:57:21 -07:00
fb255edafe 1.1.4 2019-08-27 17:28:57 -07:00
f4c39f74e8 1.1.3 2019-08-27 17:05:49 -07:00
3e56e2c3e2 Rgb raw tuning of blocs (#883)
* refactor blocks

* make non-private
2019-08-27 17:05:16 -07:00
79b5f8cc88 Add rgb and reflection raw mods for color sensor (#876)
* Add reflection raw value

Add reflection raw value for color sensor

* update

* Combined rgbraw and refraw
2019-08-27 16:45:12 -07:00
312729142f 1.1.2 2019-08-27 16:42:36 -07:00
Max
5bd4aed0e1 Multiple sensors 2 (#877)
* Fixed -1 mode in libs

* Deleted todo
2019-08-27 16:34:55 -07:00
cfaa4ae3ef migrate build to travis 2019-08-27 16:29:18 -07:00
faa839d59f 1.1.1 2019-08-27 16:26:37 -07:00
630687bfce bump to 1.1 2019-08-27 16:26:19 -07:00
2b300a4094 Maximmasterr set settle (#882)
* Added set settle time

* updated blocks
2019-08-27 14:57:28 -07:00
5fb8c0de6e delete package-lock.json 2019-08-27 14:45:25 -07:00
1f65cd59a8 Fixes to "Line Following in Loop" Sample Solutions (#871)
Sample Solutions were wrong for both Methods of Line Following in a Loop
2019-08-27 14:27:20 -07:00
17 changed files with 394 additions and 4852 deletions

9
.travis.yml Normal file
View File

@ -0,0 +1,9 @@
language: node_js
node_js:
- "8.9.0"
script:
- "node node_modules/pxt-core/built/pxt.js travis"
sudo: false
cache:
directories:
- node_modules

View File

@ -1,10 +1,8 @@
# LEGO® MINDSTORMS® Education EV3 for Microsoft MakeCode # LEGO® MINDSTORMS® Education EV3 for Microsoft MakeCode [![Build Status](https://travis-ci.org/microsoft/pxt-ev3.svg?branch=master)](https://travis-ci.org/microsoft/pxt-ev3)
[![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://makecode.mindstorms.com This repo contains the editor target hosted at https://makecode.mindstorms.com
## Local Dev setup ## Local setup
These instructions assume familiarity with dev tools and languages. These instructions assume familiarity with dev tools and languages.
@ -12,10 +10,6 @@ These instructions assume familiarity with dev tools and languages.
* install Docker; make sure `docker` command is in your `PATH` * install Docker; make sure `docker` command is in your `PATH`
* (optional) install [Visual Studio Code](https://code.visualstudio.com/) * (optional) install [Visual Studio Code](https://code.visualstudio.com/)
In a common folder,
* clone https://github.com/Microsoft/pxt to ``pxt`` folder
* clone https://github.com/Microsoft/pxt-common-packages to ``pxt-common-packages`` folder
* clone https://github.com/Microsoft/pxt-ev3 to ``pxt-ev3`` folder * clone https://github.com/Microsoft/pxt-ev3 to ``pxt-ev3`` folder
* go to ``pxt`` and run * go to ``pxt`` and run
@ -23,6 +17,18 @@ In a common folder,
npm install npm install
``` ```
* to run the local server,
```
pxt serve --cloud
```
## Local Dev setup
In the common folder,
* clone https://github.com/Microsoft/pxt to ``pxt`` folder
* clone https://github.com/Microsoft/pxt-common-packages to ``pxt-common-packages`` folder
* go to ``pxt-common-packages`` and run * go to ``pxt-common-packages`` and run
``` ```
@ -54,9 +60,6 @@ cd libs/core
pxt deploy pxt deploy
``` ```
### Jenkins build
https://ci2.dot.net/job/Private/job/pxt_project_rainbow/job/master/
## License ## License
MIT MIT

View File

@ -190,12 +190,10 @@ if (true) {
```blocks ```blocks
forever(function () { forever(function () {
while (true) { while (sensors.color3.color() == ColorSensorColor.Black) {
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Black)
motors.largeBC.steer(-30, 50) motors.largeBC.steer(-30, 50)
} }
while (true) { while (sensors.color3.color() == ColorSensorColor.White) {
sensors.color3.pauseUntilColorDetected(ColorSensorColor.White)
motors.largeBC.steer(30, 50) motors.largeBC.steer(30, 50)
} }
}) })
@ -209,11 +207,9 @@ Else the Color Sensor detects the color white, start motors ``B`` and ``C`` (dri
```blocks ```blocks
forever(function () { forever(function () {
if (true) { if (sensors.color3.color() == ColorSensorColor.Black) {
sensors.color3.pauseUntilColorDetected(ColorSensorColor.Black)
motors.largeBC.steer(-30, 50) motors.largeBC.steer(-30, 50)
} else { } else {
sensors.color3.pauseUntilColorDetected(ColorSensorColor.White)
motors.largeBC.steer(30, 50) motors.largeBC.steer(30, 50)
} }
}) })

View File

@ -1,41 +0,0 @@
import jobs.generation.Utilities;
import jobs.generation.InternalUtilities;
def project = GithubProject
def projectName = "pxt-ev3"
[true, false].each { isPR ->
def newJobName = projectName
if (isPR) {
newJobName += "_PR"
} else {
newJobName += "_Push"
}
def newJob = job(newJobName) {
steps {
shell("chmod +x ./jenkins.sh")
shell("./jenkins.sh ${isPR}")
}
if (!isPR) {
wrappers {
credentialsBinding {
string("PXT_ACCESS_TOKEN", "pxt_access_token")
string("PXT_RELEASE_REPO", "pxt_release_repo_ev3")
string("CROWDIN_KEY", "pxt_crowdin_key")
}
}
}
}
Utilities.setMachineAffinity(newJob, "Ubuntu", "20161020")
InternalUtilities.standardJobSetup(newJob, project, isPR, "*/*")
if (isPR) {
Utilities.addGithubPRTrigger(newJob, "Default Testing")
} else {
Utilities.addGithubPushTrigger(newJob)
}
}

View File

@ -1,56 +0,0 @@
#!/usr/bin/env bash
# Set up NVM
export NVM_DIR="/home/dotnet-bot/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm install 8
# Set up build environment variables
echo ---------- Setting build environment variables
echo Git branch: $GIT_BRANCH
echo isPR: $1
originRegex="^origin/.*"
branchRegex="^origin/\K.*(?=$)"
releaseBranchRegex="^(master|v\d+)$"
if [[ "$GIT_BRANCH" =~ $originRegex ]]; then
branchName=$(echo ${GIT_BRANCH} | grep -oP $branchRegex)
echo Setting TRAVIS_BRANCH to ${branchName}
export TRAVIS_BRANCH=${branchName}
else
echo Setting TRAVIS_BRANCH to $GIT_BRANCH
export TRAVIS_BRANCH=$GIT_BRANCH
fi
if [ "$1" == "false" ]; then
echo Setting TRAVIS_PULL_REQUEST to false
export TRAVIS_PULL_REQUEST=false
if [[ "$TRAVIS_BRANCH" =~ $releaseBranchRegex ]]; then
if [[ -z $PXT_RELEASE_REPO ]]; then
echo Cannot find release repo\; skipping tag checks
else
gitTag=$(git describe --tags --exact-match 2> /dev/null)
builtTag=$(git ls-remote --tags $PXT_RELEASE_REPO | grep -o "refs/tags/$gitTag$")
echo Current tag: $gitTag
echo Built tag: $builtTag
if [[ ! -z $gitTag && -z $builtTag ]]; then
echo Built tag not found\; building tag
echo Setting TRAVIS_BRANCH to $gitTag
export TRAVIS_BRANCH=$gitTag
echo Setting TRAVIS_TAG to $gitTag
export TRAVIS_TAG=$gitTag
else
echo Not a tag build
fi
fi
fi
fi
# Perform build
npm install
npm test

View File

@ -1,5 +1,5 @@
const enum ColorSensorMode { const enum ColorSensorMode {
None = -1, None = 0,
//% block="reflected light intensity" //% block="reflected light intensity"
ReflectedLightIntensity = 0, ReflectedLightIntensity = 0,
//% block="ambient light intensity" //% block="ambient light intensity"
@ -15,7 +15,9 @@ enum LightIntensityMode {
//% block="reflected light" //% block="reflected light"
Reflected = ColorSensorMode.ReflectedLightIntensity, Reflected = ColorSensorMode.ReflectedLightIntensity,
//% block="ambient light" //% block="ambient light"
Ambient = ColorSensorMode.AmbientLightIntensity Ambient = ColorSensorMode.AmbientLightIntensity,
//% block="reflected light (raw)"
ReflectedRaw = ColorSensorMode.RefRaw
} }
const enum ColorSensorColor { const enum ColorSensorColor {
@ -93,6 +95,8 @@ namespace sensors {
|| this.mode == ColorSensorMode.AmbientLightIntensity || this.mode == ColorSensorMode.AmbientLightIntensity
|| this.mode == ColorSensorMode.ReflectedLightIntensity) || this.mode == ColorSensorMode.ReflectedLightIntensity)
return this.getNumber(NumberFormat.UInt8LE, 0) return this.getNumber(NumberFormat.UInt8LE, 0)
if (this.mode == ColorSensorMode.RefRaw || this.mode == ColorSensorMode.RgbRaw)
return this.getNumber(NumberFormat.UInt16LE, 0)
return 0 return 0
} }
@ -114,7 +118,7 @@ namespace sensors {
_update(prev: number, curr: number) { _update(prev: number, curr: number) {
if (this.calibrating) return; // simply ignore data updates while calibrating if (this.calibrating) return; // simply ignore data updates while calibrating
if (this.mode == ColorSensorMode.Color) if (this.mode == ColorSensorMode.Color || this.mode == ColorSensorMode.RgbRaw || this.mode == ColorSensorMode.RefRaw)
control.raiseEvent(this._id, this._colorEventValue(curr)); control.raiseEvent(this._id, this._colorEventValue(curr));
else else
this.thresholdDetector.setLevel(curr); this.thresholdDetector.setLevel(curr);
@ -179,6 +183,22 @@ namespace sensors {
return this.getNumber(NumberFormat.UInt8LE, 0) return this.getNumber(NumberFormat.UInt8LE, 0)
} }
/**
* Get the current raw rgb values from the color sensor.
* @param sensor the color sensor to query the request
*/
//% help=sensors/color-sensor/rgbraw
//% parts="colorsensor"
//% blockNamespace=sensors
//% this.fieldEditor="ports"
//% weight=98
//% group="Color Sensor"
//% blockGap=8
rgbRaw(): number[] {
this.setMode(ColorSensorMode.RgbRaw);
return [this.getNumber(NumberFormat.UInt16LE, 0), this.getNumber(NumberFormat.UInt16LE, 2), this.getNumber(NumberFormat.UInt16LE, 4)];
}
/** /**
* Registers code to run when the ambient light changes. * Registers code to run when the ambient light changes.
* @param condition the light condition * @param condition the light condition
@ -229,7 +249,12 @@ namespace sensors {
//% group="Color Sensor" //% group="Color Sensor"
light(mode: LightIntensityMode) { light(mode: LightIntensityMode) {
this.setMode(<ColorSensorMode><number>mode) this.setMode(<ColorSensorMode><number>mode)
return this.getNumber(NumberFormat.UInt8LE, 0) switch(mode) {
case LightIntensityMode.ReflectedRaw:
return this.reflectedLightRaw();
default:
return this.getNumber(NumberFormat.UInt8LE, 0)
}
} }
/** /**
@ -248,6 +273,15 @@ namespace sensors {
return this.light(LightIntensityMode.Reflected); return this.light(LightIntensityMode.Reflected);
} }
/**
* Gets the raw reflection light value
*/
//%
reflectedLightRaw(): number {
this.setMode(ColorSensorMode.RefRaw);
return this.getNumber(NumberFormat.UInt16LE, 0);
}
/** /**
* Set a threshold value * Set a threshold value
* @param condition the dark or bright light condition * @param condition the dark or bright light condition

View File

@ -159,12 +159,6 @@ namespace brick {
if (sl[i]) if (sl[i])
ret |= 1 << i ret |= 1 << i
} }
// this needs to be done in query(), which is run without the main JS execution mutex
// otherwise, while(true){} will lock the device
if (ret & DAL.BUTTON_ID_ESCAPE) {
motors.stopAll(); // ensuring that all motors are off
control.reset()
}
return ret return ret
} }

View File

@ -25,8 +25,17 @@ namespace sensors.internal {
}) })
} }
export function bufferToString(buf: Buffer): string {
let s = ''
for (let i = 0; i < buf.length; i++)
s += String.fromCharCode(buf[i])
return s
}
let analogMM: MMap let analogMM: MMap
let uartMM: MMap let uartMM: MMap
let IICMM: MMap
let devcon: Buffer let devcon: Buffer
let sensorInfos: SensorInfo[] let sensorInfos: SensorInfo[]
@ -36,11 +45,13 @@ namespace sensors.internal {
sensors: Sensor[] sensors: Sensor[]
connType: number connType: number
devType: number devType: number
iicid: string
constructor(p: number) { constructor(p: number) {
this.port = p this.port = p
this.connType = DAL.CONN_NONE this.connType = DAL.CONN_NONE
this.devType = DAL.DEVICE_TYPE_NONE this.devType = DAL.DEVICE_TYPE_NONE
this.iicid = ''
this.sensors = [] this.sensors = []
} }
} }
@ -57,20 +68,21 @@ namespace sensors.internal {
uartMM = control.mmap("/dev/lms_uart", UartOff.Size, 0) uartMM = control.mmap("/dev/lms_uart", UartOff.Size, 0)
if (!uartMM) control.fail("no uart sensor") if (!uartMM) control.fail("no uart sensor")
forever(() => { IICMM = control.mmap("/dev/lms_iic", IICOff.Size, 0)
detectDevices() if (!IICMM) control.fail("no iic sensor")
pause(500)
})
for (let info_ of sensorInfos) { unsafePollForChanges(500,
let info = info_ () => { return hashDevices(); },
(prev, curr) => { detectDevices();
});
sensorInfos.forEach(info => {
unsafePollForChanges(50, () => { unsafePollForChanges(50, () => {
if (info.sensor) return info.sensor._query() if (info.sensor) return info.sensor._query()
return 0 return 0
}, (prev, curr) => { }, (prev, curr) => {
if (info.sensor) info.sensor._update(prev, curr) if (info.sensor) info.sensor._update(prev, curr)
}) })
} })
} }
@ -89,6 +101,15 @@ namespace sensors.internal {
//serial.writeLine("UART " + port + " / " + mode + " - " + info) //serial.writeLine("UART " + port + " / " + mode + " - " + info)
} }
export function readIICID(port: number) {
const buf = output.createBuffer(IICStr.Size)
buf[IICStr.Port] = port
IICMM.ioctl(IO.IIC_READ_TYPE_INFO, buf)
const manufacturer = bufferToString(buf.slice(IICStr.Manufacturer, 8))
const sensorType = bufferToString(buf.slice(IICStr.SensorType, 8))
return manufacturer + sensorType;
}
export function getBatteryInfo(): { temp: number; current: number } { export function getBatteryInfo(): { temp: number; current: number } {
init(); init();
return { return {
@ -97,52 +118,87 @@ namespace sensors.internal {
} }
} }
function detectDevices() { function hashDevices(): number {
let conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS) const conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
let numChanged = 0 let r = 0;
for(let i = 0; i < conns.length; ++i) {
r = (r << 8 | conns[i]);
}
return r;
}
for (let info of sensorInfos) { let nonActivated = 0;
let newConn = conns[info.port] function detectDevices() {
if (newConn == info.connType) control.dmesg(`detect devices (${nonActivated} na)`)
continue const conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
let numChanged = 0;
const uartSensors: SensorInfo[] = [];
for (const sensorInfo of sensorInfos) {
const newConn = conns[sensorInfo.port]
if (newConn == sensorInfo.connType) {
// control.dmesg(`connection unchanged ${newConn} at ${sensorInfo.port}`)
continue;
}
numChanged++ numChanged++
info.connType = newConn sensorInfo.connType = newConn
info.devType = DAL.DEVICE_TYPE_NONE sensorInfo.devType = DAL.DEVICE_TYPE_NONE
if (newConn == DAL.CONN_INPUT_UART) { if (newConn == DAL.CONN_INPUT_UART) {
control.dmesg(`new UART connection at ${info.port}`) control.dmesg(`new UART connection at ${sensorInfo.port}`)
setUartMode(info.port, 0) updateUartMode(sensorInfo.port, 0);
let uinfo = readUartInfo(info.port, 0) uartSensors.push(sensorInfo);
info.devType = uinfo[TypesOff.Type] } else if (newConn == DAL.CONN_NXT_IIC) {
control.dmesg(`UART type ${info.devType}`) control.dmesg(`new IIC connection at ${sensorInfo.port}`)
sensorInfo.devType = DAL.DEVICE_TYPE_IIC_UNKNOWN
sensorInfo.iicid = readIICID(sensorInfo.port)
control.dmesg(`IIC ID ${sensorInfo.iicid.length}`)
} else if (newConn == DAL.CONN_INPUT_DUMB) { } else if (newConn == DAL.CONN_INPUT_DUMB) {
control.dmesg(`new DUMB connection at ${info.port}`) control.dmesg(`new DUMB connection at ${sensorInfo.port}`)
// TODO? for now assume touch // TODO? for now assume touch
info.devType = DAL.DEVICE_TYPE_TOUCH sensorInfo.devType = DAL.DEVICE_TYPE_TOUCH
} else if (newConn == DAL.CONN_NONE || newConn == 0) { } else if (newConn == DAL.CONN_NONE || newConn == 0) {
control.dmesg(`disconnect at ${info.port}`) control.dmesg(`disconnect at port ${sensorInfo.port}`)
} else { } else {
control.dmesg(`unknown connection type: ${newConn} at ${info.port}`) control.dmesg(`unknown connection type: ${newConn} at ${sensorInfo.port}`)
} }
} }
if (numChanged == 0) if (uartSensors.length > 0) {
setUartModes();
for (const sensorInfo of uartSensors) {
let uinfo = readUartInfo(sensorInfo.port, 0)
sensorInfo.devType = uinfo[TypesOff.Type]
control.dmesg(`UART type ${sensorInfo.devType}`)
}
}
if (numChanged == 0 && nonActivated == 0)
return return
for (let si of sensorInfos) { control.dmesg(`updating sensor status`)
if (si.sensor && si.sensor._deviceType() != si.devType) { nonActivated = 0;
si.sensor = null for (const sensorInfo of sensorInfos) {
} if (sensorInfo.devType == DAL.DEVICE_TYPE_IIC_UNKNOWN) {
if (si.devType != DAL.DEVICE_TYPE_NONE) { sensorInfo.sensor = sensorInfo.sensors.filter(s => s._IICId() == sensorInfo.iicid)[0]
// TODO figure out compiler problem when '|| null' is added here! if (!sensorInfo.sensor) {
si.sensor = si.sensors.filter(s => s._deviceType() == si.devType)[0] control.dmesg(`sensor not found for iicid=${sensorInfo.iicid} at ${sensorInfo.port}`)
if (si.sensor == null) { nonActivated++;
control.dmesg(`sensor not found for type=${si.devType} at ${si.port}`)
} else { } else {
control.dmesg(`sensor connected type=${si.devType} at ${si.port}`) control.dmesg(`sensor connected iicid=${sensorInfo.iicid} at ${sensorInfo.port}`)
si.sensor._activated() sensorInfo.sensor._activated()
}
} else if (sensorInfo.devType != DAL.DEVICE_TYPE_NONE) {
sensorInfo.sensor = sensorInfo.sensors.filter(s => s._deviceType() == sensorInfo.devType)[0]
if (!sensorInfo.sensor) {
control.dmesg(`sensor not found for type=${sensorInfo.devType} at ${sensorInfo.port}`)
nonActivated++;
} else {
control.dmesg(`sensor connected type=${sensorInfo.devType} at ${sensorInfo.port}`)
sensorInfo.sensor._activated()
} }
} }
} }
control.dmesg(`detect devices done`)
} }
export class Sensor extends control.Component { export class Sensor extends control.Component {
@ -187,6 +243,10 @@ namespace sensors.internal {
_deviceType() { _deviceType() {
return 0 return 0
} }
_IICId() {
return ''
}
} }
export class AnalogSensor extends Sensor { export class AnalogSensor extends Sensor {
@ -212,7 +272,6 @@ namespace sensors.internal {
_activated() { _activated() {
this.realmode = 0 this.realmode = 0
// uartReset(this.port) // TODO is it ever needed?
this._setMode(this.mode) this._setMode(this.mode)
} }
@ -243,6 +302,55 @@ namespace sensors.internal {
} }
} }
export class IICSensor extends Sensor {
protected mode: number // the mode user asked for
protected realmode: number // the mode the hardware is in
private readLength: number
constructor(port: number) {
super(port)
this.mode = 0
this.realmode = 0
this.readLength = 1;
}
_activated() {
this.realmode = 0
this._setMode(this.mode)
}
protected _setMode(m: number) {
let v = m | 0
this.mode = v
if (!this.isActive()) return
if (this.realmode != this.mode) {
this.realmode = v
setIICMode(this._port, this._deviceType(), v)
}
}
getBytes(): Buffer {
return getIICBytes(this.isActive() ? this._port : -1, this.readLength)
}
getNumber(fmt: NumberFormat, off: number) {
if (!this.isActive())
return 0
return getIICNumber(this.readLength, fmt, off, this._port)
}
transaction(deviceAddress: number, write: number[], read: number) {
this.readLength = read;
transactionIIC(this._port, deviceAddress, write, read)
}
_deviceType() {
return DAL.DEVICE_TYPE_IIC_UNKNOWN
}
}
export const iicsensor = new IICSensor(3)
function uartReset(port: number) { function uartReset(port: number) {
if (port < 0) return if (port < 0) return
control.dmesg(`UART reset at ${port}`) control.dmesg(`UART reset at ${port}`)
@ -267,6 +375,7 @@ namespace sensors.internal {
} }
function uartClearChange(port: number) { function uartClearChange(port: number) {
control.dmesg(`UART clear change`);
const UART_DATA_READY = 8 const UART_DATA_READY = 8
const UART_PORT_CHANGED = 1 const UART_PORT_CHANGED = 1
while (true) { while (true) {
@ -288,20 +397,43 @@ namespace sensors.internal {
} }
} }
function setUartModes() {
control.dmesg(`UART set modes`)
uartMM.ioctl(IO.UART_SET_CONN, devcon)
const ports: number[] = [];
for (let port = 0; port < DAL.NUM_INPUTS; ++port) {
if (devcon.getNumber(NumberFormat.Int8LE, DevConOff.Connection + port) == DAL.CONN_INPUT_UART) {
ports.push(port);
}
}
while (ports.length) {
const port = ports.pop();
const status = waitNonZeroUartStatus(port)
control.dmesg(`UART set mode ${status} at ${port}`);
}
}
function updateUartMode(port: number, mode: number) {
control.dmesg(`UART set mode to ${mode} at ${port}`)
devcon.setNumber(NumberFormat.Int8LE, DevConOff.Connection + port, DAL.CONN_INPUT_UART)
devcon.setNumber(NumberFormat.Int8LE, DevConOff.Type + port, 33)
devcon.setNumber(NumberFormat.Int8LE, DevConOff.Mode + port, mode)
}
function setUartMode(port: number, mode: number) { function setUartMode(port: number, mode: number) {
const UART_PORT_CHANGED = 1 const UART_PORT_CHANGED = 1
while (true) { while (true) {
if (port < 0) return if (port < 0) return
control.dmesg(`UART set mode to ${mode} at ${port}`) updateUartMode(port, mode);
devcon.setNumber(NumberFormat.Int8LE, DevConOff.Connection + port, DAL.CONN_INPUT_UART)
devcon.setNumber(NumberFormat.Int8LE, DevConOff.Type + port, 33)
devcon.setNumber(NumberFormat.Int8LE, DevConOff.Mode + port, mode)
uartMM.ioctl(IO.UART_SET_CONN, devcon) uartMM.ioctl(IO.UART_SET_CONN, devcon)
let status = waitNonZeroUartStatus(port) let status = waitNonZeroUartStatus(port)
if (status & UART_PORT_CHANGED) { if (status & UART_PORT_CHANGED) {
control.dmesg(`UART clear changed at ${port}`)
uartClearChange(port) uartClearChange(port)
} else { } else {
break control.dmesg(`UART status ${status}`);
break;
} }
pause(10) pause(10)
} }
@ -322,6 +454,48 @@ namespace sensors.internal {
UartOff.Raw + DAL.MAX_DEVICE_DATALENGTH * 300 * port + DAL.MAX_DEVICE_DATALENGTH * index + off) UartOff.Raw + DAL.MAX_DEVICE_DATALENGTH * 300 * port + DAL.MAX_DEVICE_DATALENGTH * index + off)
} }
export function setIICMode(port: number, type: number, mode: number) {
if (port < 0) return;
devcon.setNumber(NumberFormat.Int8LE, DevConOff.Connection + port, DAL.CONN_NXT_IIC)
devcon.setNumber(NumberFormat.Int8LE, DevConOff.Type + port, type)
devcon.setNumber(NumberFormat.Int8LE, DevConOff.Mode + port, mode)
IICMM.ioctl(IO.IIC_SET_CONN, devcon)
}
export function transactionIIC(port: number, deviceAddress: number, writeBuf: number[], readLen: number) {
if (port < 0) return;
let iicdata = output.createBuffer(IICDat.Size)
iicdata.setNumber(NumberFormat.Int8LE, IICDat.Port, port)
iicdata.setNumber(NumberFormat.Int8LE, IICDat.Repeat, 0)
iicdata.setNumber(NumberFormat.Int16LE, IICDat.Time, 0)
iicdata.setNumber(NumberFormat.Int8LE, IICDat.WrLng, writeBuf.length + 1)
for (let i = 0; i < writeBuf.length; i++)
iicdata.setNumber(NumberFormat.Int8LE, IICDat.WrData + i + 1, writeBuf[i])
iicdata.setNumber(NumberFormat.Int8LE, IICDat.WrData, deviceAddress)
iicdata.setNumber(NumberFormat.Int8LE, IICDat.RdLng, readLen)
IICMM.ioctl(IO.IIC_SETUP, iicdata)
}
export function getIICBytes(port: number, length: number) {
if (port < 0) return output.createBuffer(length);
let index = IICMM.getNumber(NumberFormat.UInt16LE, IICOff.Actual + port * 2);
let buf = IICMM.slice(
IICOff.Raw + DAL.MAX_DEVICE_DATALENGTH * 300 * port + DAL.MAX_DEVICE_DATALENGTH * index,
length
);
// Reverse
for (let i = 0; i < length / 2; i++) {
let c = buf[i]
buf[i] = buf[length - i - 1]
buf[length - i - 1] = c
}
return buf;
}
export function getIICNumber(length: number, format: NumberFormat, off: number, port: number) {
return getIICBytes(port, length).getNumber(format, off)
}
const enum NxtColOff { const enum NxtColOff {
Calibration = 0, // uint32[4][3] Calibration = 0, // uint32[4][3]
@ -405,6 +579,52 @@ namespace sensors.internal {
Size = 58 Size = 58
} }
const enum IICOff {
TypeData = 0, // Types[8][4]
Repeat = 1792, // uint16[300][4]
Raw = 4192, // int8[32][300][4]
Actual = 42592, // uint16[4]
LogIn = 42600, // uint16[4]
Status = 42608, // int8[4]
Output = 42612, // int8[32][4]
OutputLength = 42740, // int8[4]
Size = 42744
}
const enum IICCtlOff {
TypeData = 0, // Types
Port = 56, // int8
Mode = 57, // int8
Size = 58
}
const enum IICDat {
Result = 0, // result
Port = 4, // int8
Repeat = 5, // int8
Time = 6, // int16
WrLng = 8, // int8
WrData = 9, // int8[32]
RdLng = 41, // int8
RdData = 42, //int8[32]
Size = 74,
}
const enum IICStr {
Port = 0, // int8
Time = 2, // int16
Type = 4, // int8
Mode = 5, // int8
Manufacturer = 6, // int8[9]
SensorType = 15, // int[9]
SetupLng = 24, // int8
SetupString = 28, // ulong
PollLng = 32, // int8
PollString = 36, // ulong
ReadLng = 40, // int8
Size = 44
}
const enum IO { const enum IO {
UART_SET_CONN = 0xc00c7500, UART_SET_CONN = 0xc00c7500,
UART_READ_MODE_INFO = 0xc03c7501, UART_READ_MODE_INFO = 0xc03c7501,
@ -472,7 +692,7 @@ namespace sensors {
} }
public threshold(t: ThresholdState): number { public threshold(t: ThresholdState): number {
switch(t) { switch (t) {
case ThresholdState.High: return this.highThreshold; case ThresholdState.High: return this.highThreshold;
case ThresholdState.Low: return this.lowThreshold; case ThresholdState.Low: return this.lowThreshold;
default: return (this.max - this.min) / 2; default: return (this.max - this.min) / 2;
@ -512,5 +732,5 @@ namespace sensors {
break; break;
} }
} }
} }
} }

View File

@ -14,6 +14,9 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <malloc.h> #include <malloc.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include "ev3const.h"
#define THREAD_DBG(...) #define THREAD_DBG(...)
@ -144,6 +147,29 @@ static void startUsb() {
pthread_detach(pid); pthread_detach(pid);
} }
static void *exitThread(void *) {
int fd = open("/dev/lms_ui", O_RDWR, 0666);
if (fd < 0)
return 0;
uint8_t *data =
(uint8_t *)mmap(NULL, NUM_BUTTONS, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (data == MAP_FAILED) {
close(fd);
return 0;
}
for (;;) {
if (data[5])
target_reset();
sleep_core_us(50000);
}
}
static void startExitThread() {
pthread_t pid;
pthread_create(&pid, NULL, exitThread, NULL);
pthread_detach(pid);
}
void sendUsb(uint16_t code, const char *data, int len) { void sendUsb(uint16_t code, const char *data, int len) {
while (len > 0) { while (len > 0) {
int sz = len; int sz = len;
@ -489,14 +515,22 @@ void runLMS() {
} }
void stopMotors() { void stopMotors() {
uint8_t cmd[2] = { 0xA3, 0x0F }; uint8_t cmd[3] = {opOutputStop, 0x0F, 0};
int fd = open("/dev/lms_pwm", O_RDWR); int fd = open("/dev/lms_pwm", O_RDWR);
write(fd, cmd, 2); write(fd, cmd, 3);
close(fd);
}
void stopProgram() {
uint8_t cmd[1] = {opOutputProgramStop};
int fd = open("/dev/lms_pwm", O_RDWR);
write(fd, cmd, 1);
close(fd); close(fd);
} }
extern "C" void target_reset() { extern "C" void target_reset() {
stopMotors(); stopMotors();
stopProgram();
if (lmsPid) if (lmsPid)
runLMS(); runLMS();
else else
@ -510,6 +544,7 @@ void initRuntime() {
DMESG("runtime starting..."); DMESG("runtime starting...");
stopLMS(); stopLMS();
startUsb(); startUsb();
startExitThread();
pthread_t disp; pthread_t disp;
pthread_create(&disp, NULL, evtDispatcher, NULL); pthread_create(&disp, NULL, evtDispatcher, NULL);
pthread_detach(disp); pthread_detach(disp);

View File

@ -134,6 +134,7 @@ namespace motors {
protected _brake: boolean; protected _brake: boolean;
private _pauseOnRun: boolean; private _pauseOnRun: boolean;
private _initialized: boolean; private _initialized: boolean;
private _brakeSettleTime: number;
private _init: () => void; private _init: () => void;
private _run: (speed: number) => void; private _run: (speed: number) => void;
private _move: (steps: boolean, stepsOrTime: number, speed: number) => void; private _move: (steps: boolean, stepsOrTime: number, speed: number) => void;
@ -147,6 +148,7 @@ namespace motors {
this._brake = false; this._brake = false;
this._pauseOnRun = true; this._pauseOnRun = true;
this._initialized = false; this._initialized = false;
this._brakeSettleTime = 10;
this._init = init; this._init = init;
this._run = run; this._run = run;
this._move = move; this._move = move;
@ -204,6 +206,20 @@ namespace motors {
writePWM(b) writePWM(b)
} }
/**
* Set the settle time after braking in milliseconds (default is 10ms).
*/
//% blockId=motorSetBrakeSettleTime block="set %motor|brake settle time %millis|ms"
//% motor.fieldEditor="motors"
//% weight=1 blockGap=8
//% group="Properties"
//% millis.defl=200 millis.min=0 millis.max=500
setBrakeSettleTime(millis: number) {
this.init();
// ensure in [0,500]
this._brakeSettleTime = Math.max(0, Math.min(500, millis | 0))
}
/** /**
* Stops the motor(s). * Stops the motor(s).
*/ */
@ -221,8 +237,8 @@ namespace motors {
protected settle() { protected settle() {
// if we've recently completed a motor command with brake // if we've recently completed a motor command with brake
// allow 500ms for robot to settle // allow 500ms for robot to settle
if (this._brake) if (this._brake && this._brakeSettleTime > 0)
pause(500); pause(this._brakeSettleTime);
} }
protected pauseOnRun(stepsOrTime: number) { protected pauseOnRun(stepsOrTime: number) {
@ -396,7 +412,7 @@ namespace motors {
*/ */
//% blockId=outputMotorSetRegulated block="set %motor|regulated %value=toggleOnOff" //% blockId=outputMotorSetRegulated block="set %motor|regulated %value=toggleOnOff"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% weight=58 //% weight=58 blockGap=8
//% group="Properties" //% group="Properties"
//% help=motors/motor/set-regulated //% help=motors/motor/set-regulated
setRegulated(value: boolean) { setRegulated(value: boolean) {

View File

@ -1,5 +1,5 @@
const enum GyroSensorMode { const enum GyroSensorMode {
None = -1, None = 0,
Angle = 0, Angle = 0,
Rate = 1, Rate = 1,
} }

View File

@ -1,5 +1,5 @@
const enum InfraredSensorMode { const enum InfraredSensorMode {
None = -1, None = 0,
Proximity = 0, Proximity = 0,
Seek = 1, Seek = 1,
RemoteControl = 2, RemoteControl = 2,

View File

@ -1,6 +1,6 @@
{ {
"name": "storage", "name": "storage",
"description": "USB Pen-drive support and flash storage", "description": "USB Pen-drive support and flash storage - beta",
"files": [ "files": [
"storage.cpp", "storage.cpp",
"storage-core.ts", "storage-core.ts",

4670
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
{ {
"name": "pxt-ev3", "name": "pxt-ev3",
"version": "1.0.11", "version": "1.1.10",
"description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode", "description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode",
"private": true, "private": false,
"keywords": [ "keywords": [
"JavaScript", "JavaScript",
"education", "education",
@ -39,7 +39,7 @@
"webfonts-generator": "^0.4.0" "webfonts-generator": "^0.4.0"
}, },
"dependencies": { "dependencies": {
"pxt-common-packages": "0.23.56", "pxt-common-packages": "0.23.61",
"pxt-core": "4.0.9" "pxt-core": "4.0.9"
}, },
"scripts": { "scripts": {

View File

@ -16,7 +16,8 @@
"libs/infrared-sensor", "libs/infrared-sensor",
"libs/gyro-sensor", "libs/gyro-sensor",
"libs/screen", "libs/screen",
"libs/ev3" "libs/ev3",
"libs/storage"
], ],
"simulator": { "simulator": {
"autoRun": true, "autoRun": true,

View File

@ -27,6 +27,7 @@ namespace pxsim.sensors {
export function __sensorUsed(port: number, type: number) { export function __sensorUsed(port: number, type: number) {
//console.log("SENSOR INIT " + port + ", type: " + type); //console.log("SENSOR INIT " + port + ", type: " + type);
if (type == DAL.DEVICE_TYPE_IIC_UNKNOWN) return; // Ignore IIC
if (!ev3board().hasSensor(port)) { if (!ev3board().hasSensor(port)) {
const sensor = ev3board().getSensor(port, type); const sensor = ev3board().getSensor(port, type);
runtime.queueDisplayUpdate(); runtime.queueDisplayUpdate();