'************************************************************************* '* Cloudrider * '* source code server stamp * '* by * '* Dr.Godfried-Willem RAES * '* Stamp2 Hardware version 1.0 * '* Filename : * '* Code version 1.1 * '************************************************************************* ' 02.09.1997: first version code for Cloudrider BS2 master controller ' This BS2 is connected to up to 3 BS1-stamps via serial ' links, thus forming a mini-star-network. ' 06.09.1997: further developed train Ghent-Herne. ' 09.09.1997: Problems with serin, now pulsout/pulsin is used for ' communication with the 3 BS1's ' Syntax debug o.k. ' 10.09.1997: Download session & practical tests. ' Test Motor 1 ok, motor 2 must have some bug... ' bug found! wrong bit send. Solved... ' use STAMP2 CLOUD2.BS2 /1 for COM1 connection ' BOMB-laptop used for download. Win95 is impotent if it comes ' to talking to the stamp hardware... ' Now, runs o.k. on cloudrider. ' 11.09.1997: communication flags added. ' Communication speed using the pulse lenght protocol as used ' in this program is: ' Xavg = 2 / ((2^n).t0) ' wherein: ' Xavg = average througput per second ' n = number of bits used for the message ' t0 = shortest pulse duration used. ' For the BS1 t0 is always 10microseconds, for the BS2, 2 microseconds ' Thus the BS1 runs at 781 bytes per second. ' DECLARATIONS: Centrobyte VAR byte ' incoming byte byte Statusbyte VAR byte ' first byte of a message Commandbyte VAR byte ' second byte of a message Robot VAR bit ' 1 for automatic ' 0 for external control Motors VAR nib ' 4-bits is enough i VAR byte ' angle counter in robot j VAR bit ' direction of rotation flags ComFlag1 VAR bit ' bit-flags to indicate communication success or failure ComFlag2 VAR bit ComFlag3 VAR bit M1ONfaktor VAR byte M2ONfaktor VAR byte M1OFFfaktor VAR byte M2OFFfaktor VAR byte BS11command VAR byte BS12command VAR byte BS13command VAR byte Tempo VAR word t VAR word ' time-out counter TimeOutValue VAR word ' INITIALISATION: 'DIR0 = 0 :' parallel input bit 7 'DIR1 = 0 :' parallel input bit 6 'DIR2 = 0 :' parallel input bit 5 'DIR3 = 0 :' parallel input bit 4 'DIR4 = 0 :' parallel input bit 3 'DIR5 = 0 :' parallel input bit 2 'DIR6 = 0 :' parallel input bit 1 'DIR7 = 0 :' parallel input bit 0 :' or, better and shorter code: DIRL = 0 'DIR8 = 1 :' output: motor 1 on/off 'DIR9 = 1 :' output: motor 1 direction 'DIR10 = 1 :' output: motor 2 on/off 'DIR11 = 1 :' output: motor 2 direction :' or, better and shorter code: DIRC = $F 'DIR12 = 0 :' input strobe bit from centronics input 'DIR13 = 0 :' used as I/O datachannel 3 - cascade to BS1-3 'DIR14 = 0 :' used as I/O datachannel 2 - cascade to BS1-2 'DIR15 = 0 :' used as I/O datachannel 1 - cascade to BS1-1 :' set to input for handshaking! ' the logic level at rest is 0 through hardware ' resistor (10k) to ground on the BS2 board. :' or, better and shorter code: DIRD = 0 ' Initialisation of variables: Centrobyte = INL :' low byte is incoming info Robot = 1 :' default is Robot ON Commandbyte = 0 Centrobyte = 0 Statusbyte = 0 Motors = 0 i = 0 :' circular counter (16-bit) j = 0 :' motor rotation direction flag M1ONfaktor = 19 M2ONfaktor = 21 M1OFFfaktor = 20 M2OFFfaktor = 23 Tempo = 512 t = 0 :' timeout counter TimeOutValue = 5000 ComFlag1 = 0 ComFlag2 = 0 ComFlag3 = 0 ' START OF RUN-CODE:***************************************************** Begin: ' first we check the strobe byte from the ' parallel input. This is bit12, as determined ' by the hardware. ' As soon as this bit goes low, there is an external ' message for the Cloudrider on pins 0 to 7 IF IN12 = 0 THEN ParInHandler IF Robot = 1 THEN RobotKode ' this bit can only be reset by an external command. ' received via Pin0-Pin7 GOTO Begin: :' end main loop op program. END :' not strictly needed here. ' ********************************************************************** ParInHandler: :' we arive here only after detection of :' a strobe low signal. If strobe is low, there must :' be a byte to be read, so we read it... (low 8 bytes) CentroByte = INL :' wait until strobe gets high again GOSUB WachtStrobe IF CentroByte > 127 THEN StatusHandler :' if the program made it up to this point, :' a command-byte must have flown in. :' the high bit (msb) must be set. Commandbyte = Centrobyte GOTO Begin StatusHandler: :' here the statusbyte is analysed :' we could have used the BRANCH instruction also IF Statusbyte = 128 + 0 THEN AllOff :' all off IF Statusbyte = 128 + 3 THEN RobotStart :' start robot mode IF Statusbyte = 128 + 4 THEN RobotStop :' stop robot mode IF Statusbyte = 128 + 5 THEN PumpsOn :' pumps only IF Statusbyte = 128 + 6 THEN TurbiOn :' turbines only IF Statusbyte = 128 + 64 THEN AllOn :' Following commands require a second :' byte from the input port :' Statusbyte=128+1 data for BS1 follows :' Statusbyte=128+2 motor command for BS2 :' Statusbyte=128+32 data for BS1-2 follows :' Statusbyte=128+64 data for BS1-3 follows CommandHandler: :' wait until new byte flows in IF IN12 = 1 THEN CommandHandler :' now strobe must be low CommandByte = INL :' read the commandbyte GOSUB WachtStrobe :' wait until strobe is high again IF Statusbyte = 128 + 1 THEN CtrlBS1 IF Statusbyte = 128 + 2 THEN CtrlBS2 IF Statusbyte = 128 + 32 THEN CtrlBS12 :' for second BS1 IF Statusbyte = 128 + 64 THEN CtrlBS13 :' for third BS1 :' if the program arrives here, :' a non recognized Statusbyte was :' received. We should disregard it. Statusbyte = 0 Commandbyte = 0 GOTO Begin CtrlBS1: : 'SEROUT 15, 813, [CommandByte] does not work here ' because it puts the BS1's into an infinite loop if no ' serial input flows in. GOSUB WachtBS1Ready IF ComFlag1 = 0 THEN FailCtrlBS11 :' unsuccessfull communication OUTPUT 15 OUT15 = 0 :' get ready to send out a positive pulse PULSOUT 15, CommandByte * 5 :' transmit in the form of a pulselenght INPUT 15 :' make the line input again. FailCtrlBS11: Statusbyte = 0 :' reset the message bytes Commandbyte = 0 Robot = 0 GOTO Begin CtrlBS12: GOSUB WachtBS12Ready IF ComFlag2 = 0 THEN FailCtrlBS12 OUTPUT 14 OUT14 = 0 PULSOUT 14, Commandbyte * 5 INPUT 14 FailCtrlBS12: Statusbyte = 0 Commandbyte = 0 Robot = 0 :' to be written on the BS12-side... GOTO Begin CtrlBS13: GOSUB WachtBS13Ready IF ComFlag3 = 0 THEN FailCtrlBS13 OUTPUT 13 OUT13 = 0 PULSOUT 13, Commandbyte * 5 INPUT 13 FailCtrlBS13: Statusbyte = 0 Commandbyte = 0 Robot = 0 :' to be written on the BS13-side GOTO Begin CtrlBS2: :' command-byte contains now the :' bits to control the low rpm motors. :' mapping table: :' input bit: commandbyte-bit :' D0 D7 :' D1 D6 :' D2 D5 :' D3 D4 Motors = 1 * Commandbyte.BIT7 Motors = 2 * Commandbyte.BIT6 + Motors Motors = 4 * Commandbyte.BIT5 + Motors Motors = 8 * Commandbyte.BIT4 + Motors OUTC = Motors :' one nibble only Statusbyte = 0 Commandbyte = 0 Robot = 0 GOTO Begin AllOff OUTC= 0 :' command to switch the motors controlled by the bs2 off ' What pulselenght do we want to use for this command? ' a 0 pulse is of course excluded... ' so we decided to use 256 instead... GOSUB WachtBS1Ready OUTPUT 15 OUT15= 0 :' get ready to send out a positive pulse PULSOUT 15, 256 * 5 :' transmit in the form of a pulselenght INPUT 15 :' make the line input again. :' more code should be added for BS12 and BS13 GOTO Begin AllOn OUTC= $F :' BS2 motors ON GOSUB WachtBS1Ready OUTPUT 15 OUT15= 0 :' get ready to send out a positive pulse PULSOUT 15, 127 * 5 :' transmit in the form of a pulselenght INPUT 15 :' make the line input again. GOTO Begin PumpsOn GOSUB WachtBS1Ready OUTPUT 15 OUT15= 0 :' get ready to send out a positive pulse PULSOUT 15, (16+32) * 5 :' transmit in the form of a pulselenght INPUT 15 :' make the line input again. GOTO Begin TurbiOn GOSUB WachtBS1Ready OUTPUT 15 OUT15= 0 :' get ready to send out a positive pulse PULSOUT 15, 64 * 5 :' transmit in the form of a pulselenght INPUT 15 :' make the line input again. GOTO Begin RobotStart Robot = 1 OUTPUT 15 OUT15 = 0 PULSOUT 15, 512 * 5 INPUT 15 GOTO Begin RobotStop Robot = 0 ' if the robot OFF command is received, the ' activated motors are switched off GOTO Alloff ' this is a command for the BS1 GOTO Begin RobotKode ' here we put the code for automatic ' use of cloudrider... ' This is the code it runs if no external ' commands are received. ' Controll for BS2- motors as well as BS1. ' The BS1 can also run its own autonomous ' robot program, if we invent a command to ' achieve this... (done: pulse-code 512*5*2 microseconds i = i + 1 ' i = i & $FF is not needed since overflow is automatic... j = i & 1 ' 0 or 1, single bit TestM1: IF i // M1ONfaktor <> 0 THEN TestM2 IF j = 0 THEN M1Links OUT8= 0 ' motor turns clockwize OUT9= 1 OUT8= 1 GOTO TestM2 M1Links: OUT8= 0 ' motor turns counterclockwize OUT9= 0 OUT8= 1 TestM2: IF i // M2ONfaktor <> 0 THEN EindeRobot IF j = 0 THEN M2Links OUT10= 0 ' clockwize OUT11= 1 OUT10= 1 GOTO EindeRobot M2Links: OUT10= 0 ' counterclockwize OUT11= 0 OUT10= 1 EindeRobot: M1ONfaktor = SIN(i) ' SIN returns values between -127 en 127 for ' inputs ranging from 0 to 256 ' M2ONfaktor = SIN(((i / 11)* 10) // 256) M2ONfaktor = COS(i) ' Similar code now for the switch-off ' controls for the sweep motors. M1OFFfaktor = (M1ONfaktor / 4) * 3 M2OFFfaktor = (M2ONfaktor / 4) * 3 TestM1off: IF i // M1OFFfaktor <> 0 THEN TestM2off OUT8= 0 ' motor OFF TestM2off: IF i // M2OFFfaktor <> 0 THEN EindeMotorRobot OUT10= 0 ' motor OFF EindeMotorRobot: ' here we insert a delay... PAUSE Tempo ' this can later be made an interactive ' determined variable tempo. GOTO Begin END ' Subroutines: ' ************ WachtBS1Ready t = t + 1 ComFlag1 = 0 IF t > TimeOutValue THEN FailBS11 :' BS1 not listening... IF IN15 = 1 THEN WachtBS1Ready :' wait until BS1 is ready to ' receive the command... ComFlag1 = 1 FailBS11 t = 0 RETURN WachtBS12Ready t = t + 1 ComFlag2 = 0 IF t > TimeOutValue THEN FailBS12 IF IN14 = 1 THEN WachtBS12Ready ComFlag2 = 1 FailBS12 t = 0 RETURN WachtBS13Ready t = t + 1 ComFlag3 = 0 IF t > TimeOutValue THEN FailBS13 IF IN13 = 1 THEN WachtBS13Ready ComFlag3 = 1 FailBS13 t = 0 RETURN WachtStrobe :' this subroutine returns only as soon as the :' strobe signal becomes high again. :' There is no time-out provision here. IF IN12 = 0 THEN WachtStrobe RETURN