/* ** file: rcx.mashenv ** modified: Thu Jun 9 12:50:35 EST 2011 ** author: Andrew Rock */ environment rcx { purpose <# This environment supports programming a Lego Mindstorms RCX robot, via the Lejos system. #> private class { purpose <# The code must be wrapped in a class declaration. #><# There are no imports. Imports are BAD, as they cause name collisions with student program names that drive the students and tutors crazy trying to figure out. #> prelude {# public class #PROGRAM_NAME# { #} postlude {# } #} } public mandatory rewrite void main() { purpose <# A program that is organised into methods must have a {\tt main} method (a procedure with no arguments). This will be the first method to execute. {\tt mashc} automatically rewrites this method to conform to standard Java. #> prelude {# public static void main(java.lang.String[] mash_args_param) throws java.lang.Exception { #OPEN_DEBUGGER# #} postlude {# #CLOSE_DEBUGGER# } #} } private void main() { purpose <# To allow a program to call its own {\tt main} method even though it gets rewritten. Probably a bad idea, but hey, why not. #> inline {# main(null) #} } public section <#Setting up sensors#> { public final int TOUCH { purpose <# Constant to select sensor type touch. #> inline {# josx.platform.rcx.SensorConstants.SENSOR_TYPE_TOUCH #} } public final int LIGHT { purpose <# Constant to select sensor type light. #> inline {# josx.platform.rcx.SensorConstants.SENSOR_TYPE_LIGHT #} } public final int ROTATION { purpose <# Constant to select sensor type rotation. #> inline {# josx.platform.rcx.SensorConstants.SENSOR_TYPE_ROT #} } private member { purpose <# Pick a sensor port. #> inline {# private static josx.platform.rcx.Sensor mash_rcx_whichSensorPort( int port) { if (port == 1) { return josx.platform.rcx.Sensor.S1; } else if (port == 2) { return josx.platform.rcx.Sensor.S2; } else if (port == 3) { return josx.platform.rcx.Sensor.S3; } else { return null; } } #} } private member { purpose <# Pick a sensor mode. #> inline {# private static int mash_rcx_whichSensorMode(int type) { if (type == TOUCH) { return josx.platform.rcx.SensorConstants.SENSOR_MODE_BOOL; } else if (type == LIGHT) { return josx.platform.rcx.SensorConstants.SENSOR_MODE_PCT; } else if (type == ROTATION) { return josx.platform.rcx.SensorConstants.SENSOR_MODE_ANGLE; } else { return 0; } } #} } private member { purpose <# Set up a sensor. #> inline {# private static void mash_rcx_setUpSensor(int port, int type) { josx.platform.rcx.Sensor s = mash_rcx_whichSensorPort(port); s.setTypeAndMode(type, mash_rcx_whichSensorMode(type)); s.activate(); } #} } public void setUpSensor(int port, int type) { purpose <# Sets up the {\tt port} to be sensor of the given {\tt type}. #> precondition <# {\tt port} is 1, 2, or 3. #> precondition <# {\tt type} is {\tt TOUCH}, {\tt LIGHT}, or {\tt ROTATION}. #> inline {# mash_rcx_setUpSensor(#port#, #type#) #} } } public section <#Using touch sensors#> { private member { purpose <# Wait For push. #> inline {# private static void mash_rcx_waitForPush(int port) { josx.platform.rcx.Sensor s = mash_rcx_whichSensorPort(port); while (s.readBooleanValue()) { } while (!s.readBooleanValue()) { } } #} } public void waitForPush(int port) { purpose <# Makes the program wait until the touch sensor on {\tt port} is pushed. #> precondition <# {\tt port} is 1, 2, or 3. #> precondition <# The port has been set up as a touch sensor. #> inline {# mash_rcx_waitForPush(#port#) #} } private member { purpose <# Wait For let go. #> inline {# private static void mash_rcx_waitForLetGo(int port) { josx.platform.rcx.Sensor s = mash_rcx_whichSensorPort(port); while (!s.readBooleanValue()) { } while (s.readBooleanValue()) { } } #} } public void waitForLetGo(int port) { purpose <# Makes the program wait until the touch sensor on {\tt port} is let go. #> precondition <# {\tt port} is 1, 2, or 3. #> precondition <# The port has been set up as a touch sensor. #> inline {# mash_rcx_waitForLetGo(#port#) #} } public boolean isPushed(int port) { purpose <# Returns {\tt true} if and only if the button on {\tt port} is currently pushed. #> precondition <# {\tt port} is 1, 2, or 3. #> precondition <# The port has been set up as a touch sensor. #> inline {# mash_rcx_whichSensorPort(#port#).readBooleanValue() #} } } public section <#Using light sensors#> { private member { purpose <# Wait For lighter. #> inline {# private static void mash_rcx_waitForLighter(int port, int dif) { josx.platform.rcx.Sensor s = mash_rcx_whichSensorPort(port); int init = s.readValue(); while (s.readValue() < init + dif) { } } #} } public void waitForLighter(int port, int dif) { purpose <# Makes the program wait until the light sensor reading on {\tt port} is increased by {\tt dif}. #> precondition <# {\tt port} is 1, 2, or 3. #> precondition <# The port has been set up as a light sensor. #> precondition <# {\tt dif} is between 0 and 100, inclusive. 0 is no wait at all. Real light levels never really change by anything like 100. #> inline {# mash_rcx_waitForLighter(#port#, #dif#) #} } private member { purpose <# Wait For light. #> inline {# private static void mash_rcx_waitForLight(int port, int light) { josx.platform.rcx.Sensor s = mash_rcx_whichSensorPort(port); int init = s.readValue(); while (s.readValue() < light) { } } #} } public void waitForLight(int port, int light) { purpose <# Makes the program wait until the light sensor reading on {\tt port} is at least the desired {\tt light} level. #> precondition <# {\tt port} is 1, 2, or 3. #> precondition <# The port has been set up as a light sensor. #> precondition <# {\tt light} is between 0 and 100, inclusive. #> inline {# mash_rcx_waitForLight(#port#, #light#) #} } private member { purpose <# Wait For darker. #> inline {# private static void mash_rcx_waitForDarker(int port, int dif) { josx.platform.rcx.Sensor s = mash_rcx_whichSensorPort(port); int init = s.readValue(); while (s.readValue() > init - dif) { } } #} } public void waitForDarker(int port, int dif) { purpose <# Makes the program wait until the light sensor reading on {\tt port} is decreased by {\tt dif}. #> precondition <# {\tt port} is 1, 2, or 3. #> precondition <# The port has been set up as a light sensor. #> precondition <# {\tt dif} is between 0 and 100, inclusive. 0 is no wait at all. Real light levels never really change by anything like 100. #> inline {# mash_rcx_waitForDarker(#port#, #dif#) #} } private member { purpose <# Wait For dark. #> inline {# private static void mash_rcx_waitForDark(int port, int light) { josx.platform.rcx.Sensor s = mash_rcx_whichSensorPort(port); int init = s.readValue(); while (s.readValue() > light) { } } #} } public void waitForDark(int port, int light) { purpose <# Makes the program wait until the light sensor reading on {\tt port} is at most the desired {\tt light} level. #> precondition <# {\tt port} is 1, 2, or 3. #> precondition <# The port has been set up as a light sensor. #> precondition <# {\tt light} is between 0 and 100, inclusive. #> inline {# mash_rcx_waitForDark(#port#, #light#) #} } public int getLight(int port) { purpose <# Returns the current light sensor reading on {\tt port}. #> precondition <# {\tt port} is 1, 2, or 3. #> precondition <# The port has been set up as a light sensor. #> inline {# mash_rcx_whichSensorPort(#port#).readValue() #} } } public section <#Using rotation sensors#> { private member { purpose <# Wait For rotation. #> inline {# private static void mash_rcx_waitForRotation(int port, int rotation) { josx.platform.rcx.Sensor s = mash_rcx_whichSensorPort(port); int init = s.readValue(); while (java.lang.Math.abs(s.readValue() - init) < java.lang.Math.abs(rotation)) { } } #} } public void waitForRotation(int port, int rotation) { purpose <# Makes the program wait until the counter in the rotation sensor on {\tt port} has changed by at least the absolute value of {\tt rotation}. #> precondition <# {\tt port} is 1, 2, or 3. #> precondition <# The port has been set up as a rotation sensor. #> inline {# mash_rcx_waitForRotation(#port#, #rotation#) #} } public int getRotation(int port) { purpose <# Returns the current rotation sensor reading on {\tt port}. #> precondition <# {\tt port} is 1, 2, or 3. #> precondition <# The port has been set up as a rotation sensor. #> inline {# mash_rcx_whichSensorPort(#port#).readValue() #} } public void resetRotation(int port) { purpose <# Sets the counter in the rotation sensor on {\tt port} to zero. #> precondition <# {\tt port} is 1, 2, or 3. #> precondition <# The port has been set up as a rotation sensor. #> inline {# mash_rcx_whichSensorPort(#port#).setPreviousValue(0) #} } } public section <#Output port constants#> { public final int A { purpose <# Constant to select port A. #> inline {# 4 #} } public final int B { purpose <# Constant to select port B. #> inline {# 5 #} } public final int C { purpose <# Constant to select port C. #> inline {# 6 #} } private member { purpose <# Pick a motor. #> inline {# private static josx.platform.rcx.Motor mash_rcx_whichMotorPort( int port) { if (port == A) { return josx.platform.rcx.Motor.A; } else if (port == B) { return josx.platform.rcx.Motor.B; } else if (port == C) { return josx.platform.rcx.Motor.C; } else { return null; } } #} } } public section <#Using motors#> { private member { purpose <# Motor forwards. #> inline {# private static void mash_rcx_motorForward(int port, int power) { josx.platform.rcx.Motor m = mash_rcx_whichMotorPort(port); m.setPower(power); m.forward(); } #} } public void motorForward(int port, int power) { purpose <# Make the motor on {\tt port} go forwards at the given {\tt power}. #> precondition <# {\tt port} is {\tt A}, {\tt B}, or {\tt C}. #> precondition <# {\tt power} is betweeen 0 and 7, inclusive. #> inline {# mash_rcx_motorForward(#port#, #power#) #} } private member { purpose <# Motor backwards. #> inline {# private static void mash_rcx_motorBackward(int port, int power) { josx.platform.rcx.Motor m = mash_rcx_whichMotorPort(port); m.setPower(power); m.backward(); } #} } public void motorBackward(int port, int power) { purpose <# Make the motor on {\tt port} go backwards at the given {\tt power}. #> precondition <# {\tt port} is {\tt A}, {\tt B}, or {\tt C}. #> precondition <# {\tt power} is betweeen 0 and 7, inclusive. #> inline {# mash_rcx_motorBackward(#port#, #power#) #} } public void motorStop(int port) { purpose <# Stop the motor on {\tt port}. #> precondition <# {\tt port} is {\tt A}, {\tt B}, or {\tt C}. #> inline {# mash_rcx_whichMotorPort(#port#).stop() #} } public void motorFloat(int port) { purpose <# Float the motor on {\tt port}. #> precondition <# {\tt port} is {\tt A}, {\tt B}, or {\tt C}. #> inline {# mash_rcx_whichMotorPort(#port#).flt() #} } } public section <#Using lamps#> { public void lampOn(int port, int power) { purpose <# Make the lamp on {\tt port} go on at the given {\tt power}. #> precondition <# {\tt port} is {\tt A}, {\tt B}, or {\tt C}. #> precondition <# {\tt power} is betweeen 0 and 7, inclusive. #> inline {# mash_rcx_motorForward(#port#, #power#) #} } public void lampOff(int port) { purpose <# Turns the lamp on {\tt port} off. #> precondition <# {\tt port} is {\tt A}, {\tt B}, or {\tt C}. #> inline {# mash_rcx_whichMotorPort(#port#).stop() #} } } public section <#Waiting for fixed times#> { private member { purpose <# Provides a binding to {\tt Thread.sleep} that won't throw exceptions. #> inline {# private static void mash_sleep(int ms) { try { java.lang.Thread.sleep(ms); } catch (java.lang.Exception e) { } } #} } public void sleep(int ms) { purpose <# Makes the program wait for a requested number of {\tt ms} (miliseconds). #> inline {# mash_sleep(#ms#) #} } } // end section: Waiting for fixed times public section <#Making sounds#> { public void systemSound(int i) { purpose <# Play system sound number {\tt i}. The system sounds are as follows. #><# { \centering \begin{tabular}{ll} {\tt i} & \emph{description} \\ 0 & short beep \\ 1 & double beep \\ 2 & descending arpeggio \\ 3 & ascending arpeggio \\ 4 & long, low beep \\ 5 & quick ascending arpeggio \end{tabular} } ##
| i | description |
| 0 | short beep |
| 1 | double beep |
| 2 | descending arpeggio |
| 3 | ascending arpeggio |
| 4 | long, low beep |
| 5 | quick ascending arpeggio |