Compare commits

...

38 Commits

Author SHA1 Message Date
7d4ba9b2b2 0.0.27 2017-10-30 10:47:03 -07:00
71b83040e6 bump pxt-core to 2.3.5, bump pxt-common-packages to 0.12.4, 2017-10-30 10:46:56 -07:00
1976534da0 Merge pull request #28 from Microsoft/sensorscat
Aligning categories with LabView/RobotC
2017-10-30 18:46:27 +01:00
c4a9b4a381 updated brick color 2017-10-30 09:58:00 -07:00
c7d36a5e82 moving motors up 2017-10-30 09:55:36 -07:00
c8c45be057 fixing brick groups 2017-10-30 09:51:18 -07:00
7c2ea7c406 fixing more groups 2017-10-28 09:20:34 -07:00
84b98a2788 brick namespace 2017-10-28 09:13:02 -07:00
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
dfe2fe3cff brick refactoring 2017-10-27 11:05:04 -07:00
18fefa2a44 output -> motors 2017-10-27 11:01:11 -07: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
31 changed files with 910 additions and 309 deletions

1
.gitignore vendored
View File

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

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))
})
```

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

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

View File

@ -2,6 +2,14 @@
"ButtonEvent.Click|block": "click", "ButtonEvent.Click|block": "click",
"ButtonEvent.Down|block": "down", "ButtonEvent.Down|block": "down",
"ButtonEvent.Up|block": "up", "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.GreenFlash|block": "Flashing Green",
"LightsPattern.GreenPulse|block": "Pulsing Green", "LightsPattern.GreenPulse|block": "Pulsing Green",
"LightsPattern.Green|block": "Green", "LightsPattern.Green|block": "Green",
@ -17,77 +25,104 @@
"Output.B|block": "B", "Output.B|block": "B",
"Output.C|block": "C", "Output.C|block": "C",
"Output.D|block": "D", "Output.D|block": "D",
"PromixityEvent.ObjectDetected|block": "object detected",
"PromixityEvent.ObjectNear|block": "object near",
"TouchSensorEvent.Bumped|block": "bumped", "TouchSensorEvent.Bumped|block": "bumped",
"TouchSensorEvent.Pressed|block": "pressed",
"TouchSensorEvent.Released|block": "released", "TouchSensorEvent.Released|block": "released",
"TouchSensorEvent.Touched|block": "touched", "brick.Button.isPressed|block": "%button|is pressed",
"brick.Button.onEvent|block": "on %button|%event",
"brick.Button.wasPressed|block": "%button|was pressed",
"brick.buttonDown|block": "button down",
"brick.buttonEnter|block": "button enter",
"brick.buttonLeft|block": "button left",
"brick.buttonRight|block": "button right",
"brick.buttonUp|block": "button up",
"brick.pattern|block": "%pattern",
"brick.print|block": "print %text| at x: %x| y: %y",
"brick.setPixel|block": "set pixel %on| at x: %x| y: %y",
"brick.setStatusLight|block": "set status light %pattern=led_pattern",
"brick|block": "brick",
"control.raiseEvent|block": "raise event|from %src|with value %value", "control.raiseEvent|block": "raise event|from %src|with value %value",
"control|block": "control", "control|block": "control",
"input.Button.isPressed|block": "%button|is pressed", "motors.Motor.count|block": "%motor|count",
"input.Button.onEvent|block": "on %button|%event", "motors.Motor.on|block": "%motor|%onOrOff",
"input.Button.wasPressed|block": "%button|was pressed", "motors.Motor.setBrake|block": "%motor|set brake %brake",
"input.ColorSensor.ambientLight|block": "%color| ambient light", "motors.Motor.setPower|block": "%motor|set power to %speed",
"input.ColorSensor.color|block": "%color| color", "motors.Motor.setReversed|block": "%motor|set reversed %reversed",
"input.ColorSensor.reflectedLight|block": "%color| reflected light", "motors.Motor.speed|block": "%motor|speed",
"input.GyroSensor.angle|block": "%sensor|angle", "motors.Motor.tachoCount|block": "%motor|tacho count",
"input.GyroSensor.rate|block": "%sensor|rotation rate", "motors.largeMotorA|block": "large motor A",
"input.IrSensor.distance|block": "%infrared|distance", "motors.largeMotorB|block": "large motor B",
"input.IrSensor.remoteCommand|block": "%infrared|remote command", "motors.largeMotorC|block": "large motor C",
"input.TouchSensor.isTouched|block": "%sensor|is touched", "motors.largeMotorD|block": "large motor D",
"input.TouchSensor.onEvent|block": "on %sensor|%event", "motors.mediumMotorA|block": "medium motor A",
"input.UltraSonicSensor.distance|block": "%sensor|distance", "motors.mediumMotorB|block": "medium motor B",
"input.buttonDown|block": "brick button down", "motors.mediumMotorC|block": "medium motor C",
"input.buttonEnter|block": "brick button enter", "motors.mediumMotorD|block": "medium motor D",
"input.buttonLeft|block": "brick button left", "motors.stopAllMotors|block": "stop all motors",
"input.buttonRight|block": "brick button right", "motors|block": "motors",
"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.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.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.Motor.off|block": "%motor|OFF then brake %brake",
"output.Motor.onForTime|block": "%motor|ON at power %power|for %ms=timePicker|ms then brake %brake",
"output.Motor.on|block": "%motor|ON at power %power",
"output.Motor.setPower|block": "%motor|set power to %speed",
"output.Motor.speed|block": "%motor|speed",
"output.motorA|block": "motor A",
"output.motorB|block": "motor B",
"output.motorC|block": "motor C",
"output.motorD|block": "motor D",
"output.pattern|block": "%pattern",
"output.setStatusLight|block": "set status light %pattern=led_pattern",
"output|block": "output", "output|block": "output",
"screen.print|block": "print %text| at x: %x| y: %y",
"screen|block": "screen", "screen|block": "screen",
"sensors.ColorSensor.ambientLight|block": "%color| ambient light",
"sensors.ColorSensor.color|block": "%color| color",
"sensors.ColorSensor.onColorDetected|block": "on %sensor|detected %color",
"sensors.ColorSensor.reflectedLight|block": "%color| reflected light",
"sensors.GyroSensor.angle|block": "%sensor|angle",
"sensors.GyroSensor.rate|block": "%sensor|rotation rate",
"sensors.InfraredSensor.onObjectNear|block": "on %sensor|object near",
"sensors.InfraredSensor.proximity|block": "%infrared|proximity",
"sensors.InfraredSensor.remoteCommand|block": "%infrared|remote command",
"sensors.RemoteInfraredBeaconButton.isPressed|block": "%button|is pressed",
"sensors.RemoteInfraredBeaconButton.onEvent|block": "on %button|%event",
"sensors.RemoteInfraredBeaconButton.wasPressed|block": "%button|was pressed",
"sensors.TouchSensor.isTouched|block": "%sensor|is touched",
"sensors.TouchSensor.onEvent|block": "on %sensor|%event",
"sensors.UltraSonicSensor.distance|block": "%sensor|distance",
"sensors.UltraSonicSensor.onObjectNear|block": "on %sensor|object near",
"sensors.color1|block": "color sensor 1",
"sensors.color2|block": "color sensor 2",
"sensors.color3|block": "color sensor 3",
"sensors.color4|block": "color sensor 4",
"sensors.gyro1|block": "gyro sensor 1",
"sensors.gyro2|block": "gyro sensor 2",
"sensors.gyro3|block": "gyro sensor 3",
"sensors.gyro4|block": "gyro sensor 4",
"sensors.infraredSensor1|block": "infrared sensor 1",
"sensors.infraredSensor2|block": "infrared sensor 2",
"sensors.infraredSensor3|block": "infrared sensor 3",
"sensors.infraredSensor4|block": "infrared sensor 4",
"sensors.remoteButtonBottomLeft|block": "remote button bottom-left",
"sensors.remoteButtonBottomRight|block": "remote button bottom-right",
"sensors.remoteButtonCenter|block": "remote button center",
"sensors.remoteButtonTopLeft|block": "remote button top-left",
"sensors.remoteButtonTopRight|block": "remote button top-right",
"sensors.touchSensor1|block": "touch sensor 1",
"sensors.touchSensor2|block": "touch sensor 2",
"sensors.touchSensor3|block": "touch sensor 3",
"sensors.touchSensor4|block": "touch sensor 4",
"sensors.ultrasonic1|block": "ultrasonic sensor 1",
"sensors.ultrasonic2|block": "ultrasonic sensor 2",
"sensors.ultrasonic3|block": "ultrasonic sensor 3",
"sensors.ultrasonic4|block": "ultrasonic sensor 4",
"sensors|block": "sensors",
"serial|block": "serial", "serial|block": "serial",
"{id:category}Brick": "Brick",
"{id:category}Control": "Control", "{id:category}Control": "Control",
"{id:category}Input": "Input",
"{id:category}MMap": "MMap", "{id:category}MMap": "MMap",
"{id:category}Motors": "Motors",
"{id:category}Output": "Output", "{id:category}Output": "Output",
"{id:category}Screen": "Screen", "{id:category}Screen": "Screen",
"{id:category}Sensors": "Sensors",
"{id:category}Serial": "Serial", "{id:category}Serial": "Serial",
"{id:group}Brick": "Brick", "{id:group}Buttons": "Buttons",
"{id:group}Color Sensor": "Color Sensor", "{id:group}Color Sensor": "Color Sensor",
"{id:group}Gyro Sensor": "Gyro Sensor", "{id:group}Gyro Sensor": "Gyro Sensor",
"{id:group}Infrared Sensor": "Infrared Sensor", "{id:group}Infrared Sensor": "Infrared Sensor",
"{id:group}Light": "Light",
"{id:group}Motors": "Motors", "{id:group}Motors": "Motors",
"{id:group}Remote Infrared Beacon": "Remote Infrared Beacon",
"{id:group}Screen": "Screen",
"{id:group}Touch Sensor": "Touch Sensor", "{id:group}Touch Sensor": "Touch Sensor",
"{id:group}Ultrasonic Sensor": "Ultrasonic Sensor" "{id:group}Ultrasonic Sensor": "Ultrasonic Sensor"
} }

View File

@ -47,7 +47,7 @@ const enum ButtonEvent {
Down = 4, Down = 4,
} }
namespace input { namespace brick {
/** /**
* Generic button class, for device buttons and sensors. * Generic button class, for device buttons and sensors.
*/ */
@ -65,7 +65,7 @@ namespace input {
} }
//% hidden //% hidden
update(curr: boolean) { _update(curr: boolean) {
if (this._isPressed == curr) return if (this._isPressed == curr) return
this._isPressed = curr this._isPressed = curr
if (curr) { if (curr) {
@ -87,9 +87,9 @@ namespace input {
//% block="%button|is pressed" //% block="%button|is pressed"
//% blockId=buttonIsPressed //% blockId=buttonIsPressed
//% parts="brick" //% parts="brick"
//% blockNamespace=input //% blockNamespace=brick
//% weight=81 blockGap=8 //% weight=81 blockGap=8
//% group="Brick" //% group="Buttons"
isPressed() { isPressed() {
return this._isPressed return this._isPressed
} }
@ -102,9 +102,9 @@ namespace input {
//% block="%button|was pressed" //% block="%button|was pressed"
//% blockId=buttonWasPressed //% blockId=buttonWasPressed
//% parts="brick" //% parts="brick"
//% blockNamespace=input //% blockNamespace=brick
//% weight=80 blockGap=8 //% weight=80 blockGap=8
//% group="Brick" //% group="Buttons"
wasPressed() { wasPressed() {
const r = this._wasPressed const r = this._wasPressed
this._wasPressed = false this._wasPressed = false
@ -112,7 +112,7 @@ 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 button the button that needs to be clicked or used
* @param event the kind of button gesture that needs to be detected * @param event the kind of button gesture that needs to be detected
* @param body code to run when the event is raised * @param body code to run when the event is raised
@ -120,16 +120,16 @@ namespace input {
//% help=input/button/on-event //% help=input/button/on-event
//% blockId=buttonEvent block="on %button|%event" //% blockId=buttonEvent block="on %button|%event"
//% parts="brick" //% parts="brick"
//% blockNamespace=input //% blockNamespace=brick
//% weight=99 blockGap=8 //% weight=99 blockGap=8
//% group="Brick" //% group="Buttons"
onEvent(ev: ButtonEvent, body: () => void) { onEvent(ev: ButtonEvent, body: () => void) {
control.onEvent(this._id, ev, body) control.onEvent(this._id, ev, body)
} }
} }
} }
namespace input { namespace brick {
let btnsMM: MMap let btnsMM: MMap
let buttons: DevButton[] let buttons: DevButton[]
@ -155,11 +155,11 @@ namespace input {
btnsMM = control.mmap("/dev/lms_ui", DAL.NUM_BUTTONS, 0) btnsMM = control.mmap("/dev/lms_ui", DAL.NUM_BUTTONS, 0)
if (!btnsMM) control.fail("no buttons?") if (!btnsMM) control.fail("no buttons?")
buttons = [] buttons = []
input.internal.unsafePollForChanges(50, readButtons, (prev, curr) => { sensors.internal.unsafePollForChanges(50, readButtons, (prev, curr) => {
if (curr & DAL.BUTTON_ID_ESCAPE) if (curr & DAL.BUTTON_ID_ESCAPE)
control.reset() control.reset()
for (let b of buttons) for (let b of buttons)
b.update(!!(curr & b.mask)) b._update(!!(curr & b.mask))
}) })
control.dmesg("runtime started, " + control.deviceFirmwareVersion()) control.dmesg("runtime started, " + control.deviceFirmwareVersion())
} }
@ -180,31 +180,31 @@ namespace input {
/** /**
* Enter button on the EV3 Brick. * Enter button on the EV3 Brick.
*/ */
//% whenUsed block="brick button enter" weight=95 fixedInstance //% whenUsed block="button enter" weight=95 fixedInstance
export const buttonEnter: Button = new DevButton(DAL.BUTTON_ID_ENTER) export const buttonEnter: Button = new DevButton(DAL.BUTTON_ID_ENTER)
/** /**
* Left button on the EV3 Brick. * Left button on the EV3 Brick.
*/ */
//% whenUsed block="brick button left" weight=95 fixedInstance //% whenUsed block="button left" weight=95 fixedInstance
export const buttonLeft: Button = new DevButton(DAL.BUTTON_ID_LEFT) export const buttonLeft: Button = new DevButton(DAL.BUTTON_ID_LEFT)
/** /**
* Right button on the EV3 Brick. * Right button on the EV3 Brick.
*/ */
//% whenUsed block="brick button right" weight=94 fixedInstance //% whenUsed block="button right" weight=94 fixedInstance
export const buttonRight: Button = new DevButton(DAL.BUTTON_ID_RIGHT) export const buttonRight: Button = new DevButton(DAL.BUTTON_ID_RIGHT)
/** /**
* Up button on the EV3 Brick. * Up button on the EV3 Brick.
*/ */
//% whenUsed block="brick button up" weight=95 fixedInstance //% whenUsed block="button up" weight=95 fixedInstance
export const buttonUp: Button = new DevButton(DAL.BUTTON_ID_UP) export const buttonUp: Button = new DevButton(DAL.BUTTON_ID_UP)
/** /**
* Down button on the EV3 Brick. * Down button on the EV3 Brick.
*/ */
//% whenUsed block="brick button down" weight=95 fixedInstance //% whenUsed block="button down" weight=95 fixedInstance
export const buttonDown: Button = new DevButton(DAL.BUTTON_ID_DOWN) export const buttonDown: Button = new DevButton(DAL.BUTTON_ID_DOWN)
} }
@ -215,7 +215,7 @@ namespace control {
*/ */
export function deviceFirmwareVersion(): string { export function deviceFirmwareVersion(): string {
let buf = output.createBuffer(6) let buf = output.createBuffer(6)
input.internal.getBtnsMM().read(buf) brick.internal.getBtnsMM().read(buf)
let r = "" let r = ""
for (let i = 0; i < buf.length; ++i) { for (let i = 0; i < buf.length; ++i) {
let c = buf[i] let c = buf[i]
@ -226,7 +226,7 @@ namespace control {
} }
} }
namespace output { namespace brick {
let currPattern: LightsPattern let currPattern: LightsPattern
/** /**
@ -234,14 +234,14 @@ namespace output {
* @param pattern the lights pattern to use. * @param pattern the lights pattern to use.
*/ */
//% blockId=setLights block="set status light %pattern=led_pattern" //% blockId=setLights block="set status light %pattern=led_pattern"
//% weight=100 group="Brick" //% weight=100 group="Light"
export function setStatusLight(pattern: number): void { export function setStatusLight(pattern: number): void {
if (currPattern === pattern) if (currPattern === pattern)
return return
currPattern = pattern currPattern = pattern
let cmd = output.createBuffer(2) let cmd = output.createBuffer(2)
cmd[0] = pattern + 48 cmd[0] = pattern + 48
input.internal.getBtnsMM().write(cmd) brick.internal.getBtnsMM().write(cmd)
} }
@ -250,7 +250,7 @@ namespace output {
* @param pattern the lights pattern to use. eg: LightsPattern.Green * @param pattern the lights pattern to use. eg: LightsPattern.Green
*/ */
//% blockId=led_pattern block="%pattern" //% blockId=led_pattern block="%pattern"
//% shim=TD_ID colorSecondary="#6e9a36" //% shim=TD_ID colorSecondary="#6e9a36" group="Light"
//% blockHidden=true useEnumVal=1 pattern.fieldOptions.decompileLiterals=1 //% blockHidden=true useEnumVal=1 pattern.fieldOptions.decompileLiterals=1
export function pattern(pattern: LightsPattern): number { export function pattern(pattern: LightsPattern): number {
return pattern; return pattern;

View File

@ -9,17 +9,25 @@ const enum ColorSensorMode {
} }
const enum ColorSensorColor { const enum ColorSensorColor {
//% block="none"
None, None,
//% block="black"
Black, Black,
//% block="blue"
Blue, Blue,
//% block="green"
Green, Green,
//% block="yellow"
Yellow, Yellow,
//% block="red"
Red, Red,
//% block="white"
White, White,
//% block="brown"
Brown, Brown,
} }
namespace input { namespace sensors {
//% fixedInstances //% fixedInstances
export class ColorSensor extends internal.UartSensor { export class ColorSensor extends internal.UartSensor {
@ -35,6 +43,35 @@ namespace input {
this._setMode(m) this._setMode(m)
} }
_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=sensors
//% 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. * Get current ambient light value from the color sensor.
* @param color the color sensor to query the request * @param color the color sensor to query the request
@ -43,7 +80,7 @@ namespace input {
//% block="%color| ambient light" //% block="%color| ambient light"
//% blockId=colorGetAmbient //% blockId=colorGetAmbient
//% parts="colorsensor" //% parts="colorsensor"
//% blockNamespace=input //% blockNamespace=sensors
//% weight=65 blockGap=8 //% weight=65 blockGap=8
//% group="Color Sensor" //% group="Color Sensor"
ambientLight() { ambientLight() {
@ -59,7 +96,7 @@ namespace input {
//% block="%color| reflected light" //% block="%color| reflected light"
//% blockId=colorGetReflected //% blockId=colorGetReflected
//% parts="colorsensor" //% parts="colorsensor"
//% blockNamespace=input //% blockNamespace=sensors
//% weight=64 blockGap=8 //% weight=64 blockGap=8
//% group="Color Sensor" //% group="Color Sensor"
reflectedLight(): number { reflectedLight(): number {
@ -75,7 +112,7 @@ namespace input {
//% block="%color| color" //% block="%color| color"
//% blockId=colorGetColor //% blockId=colorGetColor
//% parts="colorsensor" //% parts="colorsensor"
//% blockNamespace=input //% blockNamespace=sensors
//% weight=66 blockGap=8 //% weight=66 blockGap=8
//% group="Color Sensor" //% group="Color Sensor"
color(): ColorSensorColor { color(): ColorSensorColor {

View File

@ -4,7 +4,7 @@ const enum GyroSensorMode {
Rate = 1, Rate = 1,
} }
namespace input { namespace sensors {
//% fixedInstances //% fixedInstances
export class GyroSensor extends internal.UartSensor { export class GyroSensor extends internal.UartSensor {
constructor(port: number) { constructor(port: number) {
@ -27,7 +27,7 @@ namespace input {
//% block="%sensor|angle" //% block="%sensor|angle"
//% blockId=gyroGetAngle //% blockId=gyroGetAngle
//% parts="gyroscope" //% parts="gyroscope"
//% blockNamespace=input //% blockNamespace=sensors
//% weight=65 blockGap=8 //% weight=65 blockGap=8
//% group="Gyro Sensor" //% group="Gyro Sensor"
angle() { angle() {
@ -43,7 +43,7 @@ namespace input {
//% block="%sensor|rotation rate" //% block="%sensor|rotation rate"
//% blockId=gyroGetRate //% blockId=gyroGetRate
//% parts="gyroscope" //% parts="gyroscope"
//% blockNamespace=input //% blockNamespace=sensors
//% weight=65 blockGap=8 //% weight=65 blockGap=8
//% group="Gyro Sensor" //% group="Gyro Sensor"
rate() { rate() {

View File

@ -1,4 +1,4 @@
namespace input.internal { namespace sensors.internal {
//% shim=pxt::unsafePollForChanges //% shim=pxt::unsafePollForChanges
export function unsafePollForChanges( export function unsafePollForChanges(
periodMs: number, periodMs: number,
@ -119,7 +119,8 @@ namespace input.internal {
si.sensor = null si.sensor = null
} }
if (si.devType != DAL.DEVICE_TYPE_NONE) { if (si.devType != DAL.DEVICE_TYPE_NONE) {
si.sensor = si.sensors.filter(s => s._deviceType() == si.devType)[0] || null // 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) { if (si.sensor == null) {
control.dmesg(`sensor not found for type=${si.devType} at ${si.port}`) control.dmesg(`sensor not found for type=${si.devType} at ${si.port}`)
} else { } else {
@ -139,6 +140,7 @@ namespace input.internal {
control.panic(120) control.panic(120)
this.port = port_ - 1 this.port = port_ - 1
init() init()
sensorInfos[this.port].sensors.push(this)
} }
_activated() { } _activated() { }

View File

@ -21,7 +21,7 @@ const enum IrRemoteButton {
BottomRight = 0x10, BottomRight = 0x10,
} }
namespace input { namespace sensors {
function mapButton(v: number) { function mapButton(v: number) {
switch (v) { switch (v) {
case 0: return IrRemoteButton.None case 0: return IrRemoteButton.None
@ -40,24 +40,24 @@ namespace input {
} }
} }
let buttons: Button[] let buttons: RemoteInfraredBeaconButton[]
function create(ir: IrSensor) { function create(ir: InfraredSensor) {
// it's created by referencing it // it's created by referencing it
} }
export function irButton(id: IrRemoteButton) { export function irButton(id: IrRemoteButton): RemoteInfraredBeaconButton {
if (buttons == null) { if (buttons == null) {
buttons = [] buttons = []
for (let i = 0; i < 5; ++i) { for (let i = 0; i < 5; ++i) {
buttons.push(new Button()) buttons.push(new RemoteInfraredBeaconButton(new brick.Button()))
} }
// make sure sensors are up // make sure sensors are up
create(ir1) create(infraredSensor1)
create(ir2) create(infraredSensor2)
create(ir3) create(infraredSensor3)
create(ir4) create(infraredSensor4)
} }
let num = -1 let num = -1
@ -69,29 +69,101 @@ namespace input {
return buttons[num] return buttons[num]
} }
//% fixedInstance //% fixedInstances
export class IrSensor extends internal.UartSensor { export class RemoteInfraredBeaconButton extends control.Component {
private channel: IrRemoteChannel private button: brick.Button;
constructor(button: brick.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=sensors
//% 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=sensors
//% 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=sensors
//% 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) { constructor(port: number) {
super(port) super(port)
this.channel = IrRemoteChannel.Ch0 this.channel = IrRemoteChannel.Ch0
this.proximityThreshold = 10;
irButton(0) // make sure buttons array is initalized irButton(0) // make sure buttons array is initalized
// and set the mode, as otherwise button events won't work // and set the mode, as otherwise button events won't work
this.mode = IrSensorMode.RemoteControl this.mode = IrSensorMode.RemoteControl;
} }
_query() { _query() {
if (this.mode == IrSensorMode.RemoteControl) 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 return 0
} }
_update(prev: number, curr: number) { _update(prev: number, curr: number) {
for (let i = 0; i < buttons.length; ++i) { if (this.mode == IrSensorMode.RemoteControl) {
let v = !!(curr & (1 << i)) for (let i = 0; i < buttons.length; ++i) {
buttons[i].update(v) let v = !!(curr & (1 << i))
buttons[i]._update(v)
}
} else {
if (curr)
control.raiseEvent(this._id, curr);
} }
} }
@ -102,7 +174,7 @@ namespace input {
setRemoteChannel(c: IrRemoteChannel) { setRemoteChannel(c: IrRemoteChannel) {
c = Math.clamp(0, 3, c | 0) c = Math.clamp(0, 3, c | 0)
this.channel = c this.channel = c
this.setMode(IrSensorMode.RemoteControl) this._setMode(IrSensorMode.RemoteControl)
} }
setMode(m: IrSensorMode) { setMode(m: IrSensorMode) {
@ -110,18 +182,39 @@ namespace input {
} }
/** /**
* Get the distance measured by the infrared sensor. * 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=sensors
//% 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 * @param ir the infrared sensor
*/ */
//% help=input/infrared/distance //% help=input/infrared/proximity
//% block="%infrared|distance" //% block="%infrared|proximity"
//% blockId=infraredGetDistance //% blockId=infraredGetProximity
//% parts="infrared" //% parts="infrared"
//% blockNamespace=input //% blockNamespace=sensors
//% weight=65 blockGap=8 //% weight=65 blockGap=8
//% group="Infrared Sensor" //% group="Infrared Sensor"
distance() { proximity() {
this.setMode(IrSensorMode.Proximity) this._setMode(IrSensorMode.Proximity)
return this.getNumber(NumberFormat.UInt8LE, 0) return this.getNumber(NumberFormat.UInt8LE, 0)
} }
@ -133,60 +226,61 @@ namespace input {
//% block="%infrared|remote command" //% block="%infrared|remote command"
//% blockId=infraredGetRemoteCommand //% blockId=infraredGetRemoteCommand
//% parts="infrared" //% parts="infrared"
//% blockNamespace=input //% blockNamespace=sensors
//% weight=65 blockGap=8 //% weight=65 blockGap=8
//% group="Infrared Sensor" //% group="Infrared Sensor"
remoteCommand() { remoteCommand() {
this.setMode(IrSensorMode.RemoteControl) this._setMode(IrSensorMode.RemoteControl)
return this.getNumber(NumberFormat.UInt8LE, this.channel) return this.getNumber(NumberFormat.UInt8LE, this.channel)
} }
// TODO // TODO
getDirectionAndDistance() { getDirectionAndDistance() {
this.setMode(IrSensorMode.Seek) this._setMode(IrSensorMode.Seek)
return this.getNumber(NumberFormat.UInt16LE, this.channel * 2) return this.getNumber(NumberFormat.UInt16LE, this.channel * 2)
} }
} }
//% whenUsed //% fixedInstance whenUsed block="infrared sensor 1"
export const ir1: IrSensor = new IrSensor(1) export const infraredSensor1: InfraredSensor = new InfraredSensor(1)
//% whenUsed //% fixedInstance whenUsed block="infrared sensor 2"
export const ir2: IrSensor = new IrSensor(2) export const infraredSensor2: InfraredSensor = new InfraredSensor(2)
//% whenUsed //% fixedInstance whenUsed block="infrared sensor 3"
export const ir3: IrSensor = new IrSensor(3) export const infraredSensor3: InfraredSensor = new InfraredSensor(3)
//% whenUsed //% fixedInstance whenUsed block="infrared sensor 4"
export const ir4: IrSensor = new IrSensor(4) export const infraredSensor4: InfraredSensor = new InfraredSensor(4)
/**
* Remote top-left button.
*/
//% whenUsed block="remote top-left" weight=95 fixedInstance
export const remoteTopLeft = irButton(IrRemoteButton.TopLeft)
/**
* Remote top-right button.
*/
//% whenUsed block="remote top-right" weight=95 fixedInstance
export const remoteTopRight = irButton(IrRemoteButton.TopRight)
/**
* Remote bottom-left button.
*/
//% whenUsed block="remote bottom-left" weight=95 fixedInstance
export const remoteBottomLeft = irButton(IrRemoteButton.BottomLeft)
/**
* Remote bottom-right button.
*/
//% whenUsed block="remote bottom-right" weight=95 fixedInstance
export const remoteBottomRight = irButton(IrRemoteButton.BottomRight)
/** /**
* Remote beacon (center) button. * Remote beacon (center) button.
*/ */
//% whenUsed block="remote center" weight=95 fixedInstance //% whenUsed block="remote button center" weight=95 fixedInstance
export const remoteCenter = irButton(IrRemoteButton.CenterBeacon) 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,5 +1,9 @@
//% weight=100
namespace brick {
}
//% color="#B4009E" weight=98 icon="\uf192" //% color="#B4009E" weight=98 icon="\uf192"
//% groups='["Touch Sensor", "Gyro Sensor", "Color Sensor", "Ultrasonic Sensor", "Infrared Sensor", "Remote", "Brick"]' //% groups='["Touch Sensor", "Color Sensor", "Ultrasonic Sensor", "Infrared Sensor", "Remote Infrared Beacon", "Gyro Sensor"]'
namespace input { namespace sensors {
} }

View File

@ -17,7 +17,7 @@ enum OutputType {
MiniTacho = 8, MiniTacho = 8,
} }
namespace output { namespace motors {
let pwmMM: MMap let pwmMM: MMap
let motorMM: MMap let motorMM: MMap
@ -41,7 +41,7 @@ namespace output {
buf[0] = DAL.opProgramStart buf[0] = DAL.opProgramStart
writePWM(buf) writePWM(buf)
} }
function writePWM(buf: Buffer): void { function writePWM(buf: Buffer): void {
init() init()
pwmMM.write(buf) pwmMM.write(buf)
@ -53,7 +53,7 @@ namespace output {
} }
function mkCmd(out: Output, cmd: number, addSize: number) { function mkCmd(out: Output, cmd: number, addSize: number) {
const b = createBuffer(2 + addSize) const b = output.createBuffer(2 + addSize)
b.setNumber(NumberFormat.UInt8LE, 0, cmd) b.setNumber(NumberFormat.UInt8LE, 0, cmd)
b.setNumber(NumberFormat.UInt8LE, 1, out) b.setNumber(NumberFormat.UInt8LE, 1, out)
return b return b
@ -61,64 +61,48 @@ namespace output {
function resetMotors() { function resetMotors() {
reset(Output.ALL) reset(Output.ALL)
} }
/**
* Stops all motors
*/
//% 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)
}
//% fixedInstances //% fixedInstances
export class Motor extends control.Component { export class Motor extends control.Component {
port: Output; private port: Output;
constructor(port: Output) { private large: boolean;
private brake: boolean;
constructor(port: Output, large: boolean) {
super(); super();
this.port = port; this.port = port;
this.large = large;
this.brake = false;
} }
/** /**
* Power off the motor. * Power on or off the motor.
* @param motor the motor to turn off
*/
//% blockId=outputMotorOf block="%motor|OFF then brake %brake"
//% brake.fieldEditor=toggleonoff
//% weight=100 group="Motors" blockGap=8
off(brake = false) {
const b = mkCmd(this.port, DAL.opOutputStop, 1)
b.setNumber(NumberFormat.UInt8LE, 2, brake ? 1 : 0)
writePWM(b)
}
/**
* Power on the motor.
* @param motor the motor to turn on * @param motor the motor to turn on
* @param power the motor power level from ``-100`` to ``100``, eg: 50 * @param power the motor power level from ``-100`` to ``100``, eg: 50
*/ */
//% blockId=outputMotorOn block="%motor|ON at power %power" //% blockId=outputMotorOn block="%motor|%onOrOff"
//% power.min=-100 power.max=100 //% onOrOff.fieldEditor=toggleonoff
//% weight=99 group="Motors" blockGap=8 //% weight=99 group="Motors" blockGap=8
on(power: number = 50) { on(onOrOff: boolean = true) {
this.setPower(power); if (onOrOff) {
const b = mkCmd(this.port, DAL.opOutputStart, 0) const b = mkCmd(this.port, DAL.opOutputStart, 0)
writePWM(b); writePWM(b);
} } else {
const b = mkCmd(this.port, DAL.opOutputStop, 1)
/** b.setNumber(NumberFormat.UInt8LE, 2, this.brake ? 1 : 0)
* Power on the motor for a specified number of milliseconds. writePWM(b)
* @param motor the motor to turn on }
* @param power the motor power level from ``-100`` to ``100``, eg: 50
* @param ms the number of milliseconds to turn the motor on, eg: 500
* @param brake whether or not to use the brake
*/
//% blockId=outputMotorOnForTime block="%motor|ON at power %power|for %ms=timePicker|ms then brake %brake"
//% power.min=-100 power.max=100
//% brake.fieldEditor=toggleonoff
//% weight=98 group="Motors" blockGap=8
onForTime(power: number, ms: number, brake = false) {
step(this.port, {
power,
step1: 0,
step2: ms,
step3: 0,
useSteps: false,
useBrake: brake
})
loops.pause(ms);
} }
/** /**
@ -127,7 +111,7 @@ namespace output {
* @param power the desired speed to use. eg: 50 * @param power the desired speed to use. eg: 50
*/ */
//% blockId=motorSetPower block="%motor|set power to %speed" //% blockId=motorSetPower block="%motor|set power to %speed"
//% weight=60 group="Motors" //% weight=62 group="Motors" blockGap=8
//% speed.min=-100 speed.max=100 //% speed.min=-100 speed.max=100
setPower(power: number) { setPower(power: number) {
const b = mkCmd(this.port, DAL.opOutputPower, 1) const b = mkCmd(this.port, DAL.opOutputPower, 1)
@ -135,44 +119,109 @@ namespace output {
writePWM(b) 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. * Gets motor actual speed.
* @param motor the port which connects to the motor * @param motor the port which connects to the motor
*/ */
//% blockId=motorSpeed block="%motor|speed" //% blockId=motorSpeed block="%motor|speed"
//% weight=50 group="Motors" blockGap=8 //% weight=50 group="Motors" blockGap=8
speed() { speed(): number {
return getMotorData(this.port).actualSpeed; 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="motor B" //% whenUsed fixedInstance block="large motor A"
export const motorB = new Motor(Output.B); export const largeMotorA = new Motor(Output.A, true);
//% whenUsed fixedInstance block="motor C" //% whenUsed fixedInstance block="large motor B"
export const motorC = new Motor(Output.C); export const largeMotorB = new Motor(Output.B, true);
//% whenUsed fixedInstance block="motor A" //% whenUsed fixedInstance block="large motor C"
export const motorA = new Motor(Output.A); export const largeMotorC = new Motor(Output.C, true);
//% whenUsed fixedInstance block="motor D" //% whenUsed fixedInstance block="large motor D"
export const motorD = new Motor(Output.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) { function reset(out: Output) {
let b = mkCmd(out, DAL.opOutputReset, 0) let b = mkCmd(out, DAL.opOutputReset, 0)
writePWM(b) writePWM(b)
} }
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)
}
}
}
function outOffset(out: Output) { function outOffset(out: Output) {
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) { for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
if (out & (1 << i)) if (out & (1 << i))
@ -197,12 +246,6 @@ namespace output {
} }
} }
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)
}
interface StepOptions { interface StepOptions {
power?: number; power?: number;
speed?: number; // either speed or power has to be present speed?: number; // either speed or power has to be present

View File

@ -1,4 +1,4 @@
namespace screen { namespace brick {
//% shim=screen::_setPixel //% shim=screen::_setPixel
function _setPixel(p0: uint32, p1: uint32, mode: Draw): void { } function _setPixel(p0: uint32, p1: uint32, mode: Draw): void { }
@ -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="Screen"
//% 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 x |= 0
y |= 0 y |= 0
if (0 <= x && x < DAL.LCD_WIDTH && 0 <= y && y < DAL.LCD_HEIGHT) 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. * Show text on the screen.
@ -93,7 +101,7 @@ namespace screen {
* @param y the starting position's x coordinate, eg: 0 * @param y the starting position's x coordinate, eg: 0
*/ */
//% blockId=screen_print block="print %text| at x: %x| y: %y" //% blockId=screen_print block="print %text| at x: %x| y: %y"
//% weight=99 group="Brick" blockNamespace=output inlineInputMode="inline" //% weight=99 group="Screen" inlineInputMode="inline" blockGap=8
//% x.min=0 x.max=178 y.min=0 y.max=128 //% x.min=0 x.max=178 y.min=0 y.max=128
export function print(text: string, x: number, y: number, mode = Draw.Normal) { export function print(text: string, x: number, y: number, mode = Draw.Normal) {
x |= 0 x |= 0
@ -119,7 +127,7 @@ namespace screen {
iconBuf.fill(0, 2) iconBuf.fill(0, 2)
else else
iconBuf.write(2, currFont.data.slice(idx, charSize)) iconBuf.write(2, currFont.data.slice(idx, charSize))
drawIcon(x, y, iconBuf, mode) screen.drawIcon(x, y, iconBuf, mode)
x += double * currFont.charWidth x += double * currFont.charWidth
} }
} }

View File

@ -2,46 +2,46 @@ screen.clear()
screen.print("PXT!", 10, 30, Draw.Quad) screen.print("PXT!", 10, 30, Draw.Quad)
screen.drawRect(40, 40, 20, 10, Draw.Fill) screen.drawRect(40, 40, 20, 10, Draw.Fill)
output.setStatusLight(LightsPattern.Orange) motors.setStatusLight(LightsPattern.Orange)
screen.drawIcon(100, 50, screen.doubleIcon(screen.heart), Draw.Double | Draw.Transparent) screen.drawIcon(100, 50, screen.doubleIcon(screen.heart), Draw.Double | Draw.Transparent)
input.buttonEnter.onEvent(ButtonEvent.Click, () => { sensors.buttonEnter.onEvent(ButtonEvent.Click, () => {
screen.clear() screen.clear()
}) })
input.buttonLeft.onEvent(ButtonEvent.Click, () => { sensors.buttonLeft.onEvent(ButtonEvent.Click, () => {
screen.drawRect(10, 70, 20, 10, Draw.Fill) screen.drawRect(10, 70, 20, 10, Draw.Fill)
output.setStatusLight(LightsPattern.Red) motors.setStatusLight(LightsPattern.Red)
screen.setFont(screen.microbitFont()) screen.setFont(screen.microbitFont())
}) })
input.buttonRight.onEvent(ButtonEvent.Click, () => { sensors.buttonRight.onEvent(ButtonEvent.Click, () => {
screen.print("Right!", 10, 60) screen.print("Right!", 10, 60)
}) })
input.buttonDown.onEvent(ButtonEvent.Click, () => { sensors.buttonDown.onEvent(ButtonEvent.Click, () => {
screen.print("Down! ", 10, 60) screen.print("Down! ", 10, 60)
}) })
input.buttonUp.onEvent(ButtonEvent.Click, () => { sensors.buttonUp.onEvent(ButtonEvent.Click, () => {
screen.print("Up! ", 10, 60) screen.print("Up! ", 10, 60)
}) })
let num = 0 let num = 0
input.touchSensor1.onEvent(TouchSensorEvent.Bumped, () => { sensors.touchSensor1.onEvent(TouchSensorEvent.Bumped, () => {
screen.print("Click! " + num, 10, 60) screen.print("Click! " + num, 10, 60)
num++ num++
}) })
input.remoteTopLeft.onEvent(ButtonEvent.Click, () => { sensors.remoteButtonTopLeft.onEvent(ButtonEvent.Click, () => {
screen.print("TOPLEFT " + num, 10, 60) screen.print("TOPLEFT " + num, 10, 60)
num++ num++
}) })
input.remoteTopRight.onEvent(ButtonEvent.Down, () => { sensors.remoteButtonTopRight.onEvent(ButtonEvent.Down, () => {
screen.print("TOPRIGH " + num, 10, 60) screen.print("TOPRIGH " + num, 10, 60)
num++ num++
}) })

View File

@ -4,23 +4,23 @@
* Touch sensor interactions * Touch sensor interactions
*/ */
const enum TouchSensorEvent { const enum TouchSensorEvent {
//% block="touched" //% block="pressed"
Touched = 4, Pressed = 4,
//% block="bumped" //% block="bumped"
Bumped = 1, Bumped = 1,
//% block="released" //% block="released"
Released = 3, Released = 3,
} }
namespace input { namespace sensors {
//% fixedInstances //% fixedInstances
export class TouchSensor extends internal.AnalogSensor { export class TouchSensor extends internal.AnalogSensor {
private button: Button; private button: brick.Button;
constructor(port: number) { constructor(port: number) {
super(port) super(port)
this.button = new Button(); this.button = new brick.Button();
} }
_query() { _query() {
@ -28,7 +28,7 @@ namespace input {
} }
_update(prev: number, curr: number) { _update(prev: number, curr: number) {
this.button.update(curr > 0) this.button._update(curr > 0)
} }
_deviceType() { _deviceType() {
@ -43,7 +43,7 @@ namespace input {
//% block="%sensor|is touched" //% block="%sensor|is touched"
//% blockId=touchIsTouched //% blockId=touchIsTouched
//% parts="touch" //% parts="touch"
//% blockNamespace=input //% blockNamespace=sensors
//% weight=81 blockGap=8 //% weight=81 blockGap=8
//% group="Touch Sensor" //% group="Touch Sensor"
isTouched() { isTouched() {
@ -59,7 +59,7 @@ namespace input {
//% help=input/touch/on-event //% help=input/touch/on-event
//% blockId=touchEvent block="on %sensor|%event" //% blockId=touchEvent block="on %sensor|%event"
//% parts="touch" //% parts="touch"
//% blockNamespace=input //% blockNamespace=sensors
//% weight=99 blockGap=8 //% weight=99 blockGap=8
//% group="Touch Sensor" //% group="Touch Sensor"
onEvent(ev: TouchSensorEvent, body: () => void) { onEvent(ev: TouchSensorEvent, body: () => void) {

View File

@ -1,15 +1,58 @@
namespace input { const enum PromixityEvent {
//% block="object near"
ObjectNear = 1,
//% block="object detected"
ObjectDetected = 2
}
namespace sensors {
//% fixedInstances //% fixedInstances
export class UltraSonicSensor extends internal.UartSensor { export class UltraSonicSensor extends internal.UartSensor {
private promixityThreshold: number;
constructor(port: number) { constructor(port: number) {
super(port) super(port)
this.promixityThreshold = 10;
} }
_deviceType() { _deviceType() {
return DAL.DEVICE_TYPE_ULTRASONIC return DAL.DEVICE_TYPE_ULTRASONIC
} }
_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=sensors
//% 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 * Gets the distance from the sonar in millimeters
* @param sensor the ultrasonic sensor port * @param sensor the ultrasonic sensor port
@ -18,13 +61,13 @@ namespace input {
//% block="%sensor|distance" //% block="%sensor|distance"
//% blockId=sonarGetDistance //% blockId=sonarGetDistance
//% parts="ultrasonic" //% parts="ultrasonic"
//% blockNamespace=input //% blockNamespace=sensors
//% weight=65 blockGap=8 //% weight=65 blockGap=8
//% group="Ultrasonic Sensor" //% group="Ultrasonic Sensor"
distance() { distance() {
// it supposedly also has an inch mode, but we stick to mm // it supposedly also has an inch mode, but we stick to mm
this._setMode(0) this._setMode(0)
return this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff return this.getNumber(NumberFormat.UInt16LE, 0) & 0x0fff;
} }
} }

View File

@ -1,11 +1,16 @@
//% color="#D42878" //% color="#00A5C8" weight=100
namespace input { //% groups='["Light", "Buttons", "Screen"]'
namespace brick {
} }
//% color="#8AC044" weight=90 icon="\uf185"
//% groups='["Motors", "Brick"]' //% color="#8AC044" weight=95 icon="\uf185"
namespace output { namespace motors {
}
//% color="#D42878" weight=90
namespace sensors {
} }
//% color="#DF5014" weight=80 //% color="#DF5014" weight=80

View File

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

View File

@ -100,10 +100,6 @@
{ {
"name": "Reference", "name": "Reference",
"path": "/reference" "path": "/reference"
},
{
"name": "Buy",
"path": "https://www.lego.com/en-us/mindstorms/products/mindstorms-ev3-31313"
} }
], ],
"showHomeScreen": true, "showHomeScreen": 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

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