BrickTronic Posted Friday at 09:54 AM Posted Friday at 09:54 AM 14 hours ago, AJB2K3 said: Hay guys, did you get anywhere further with this? I'm building a Blockly variant for the legacy Bricks and would like to get the cybermaster included. ... Hello, Cybermaster us an "Tower" with RS232 Interface to PC and 27MHz Radio Frequency Interface to Cybermaster Pictures of the Tower : http://www.brickshelf.com/cgi-bin/gallery.cgi?i=604134 & http://www.brickshelf.com/cgi-bin/gallery.cgi?i=604133 and further http://www.brickshelf.com/cgi-bin/gallery.php?f=66485 Schematic you can find https://fccid.io/document.php?id=23750 Note that RTS = -12V and DTR=+12V is used for GND -> 5V to RS232 Level shift Programmable Prick Baudrate 0-Bit 1-Bit RCX 1.0 / 1.5 RCX 2.0 2.400Bd, Start- 8 Data-, Odd Parity- & Stop- Bit 4.800Bd, Start- 8 Data-, Odd Parity- & Stop- Bit 38kHz / 50% 76kHz / 25% Light OFF Light OFF Scout 2.400Bd, Start- 8 Data-, Odd Parity- & Stop- Bit 38kHz / 50% Light OFF Spybotic 4.800Bd, Start- 8 Data-, Odd Parity- & Stop- Bit Light ON Light OFF Cybermaster 2.400Bd, Start- 8 Data-, Odd Parity- & Stop- Bit AM 26,995MHz Programmable Prick Header Remark RCX 3 Byte 0x55 0xFF 0x00 Scout 3 Byte 0x55 0xFF 0x00 Spybotic tbd tbd Cybermaster 4 Byte 0xFE 0x00 0x00 0xFF Command to Cybermaster 1 Byte 0xFF Reply from Cybermaster Programmable Prick Command Frame RCX 0x55 0xFF 0x00 Cmd Cmd D0 D0 .. Dn Dn Chk Chk Scout 0x55 0xFF 0x00 Cmd Cmd D0 D0 .. Dn Dn Chk Chk Spybotic tbd Cybermaster 0xFE 0x00 0x00 0xFF Cmd Cmd D0 D0 .. Dn Dn Chk Chk Programmable Prick Reply Frame RCX 0x55 0xFF 0x00 Cmd Cmd D0 D0 .. Dn Dn Chk Chk Scout 0x55 0xFF 0x00 Cmd Cmd D0 D0 .. Dn Dn Chk Chk Spybotic tbd Cybermaster 0xFF Cmd Cmd D0 D0 .. Dn Dn Chk Chk Jo Quote
Chris Hocking Posted Saturday at 09:22 AM Author Posted Saturday at 09:22 AM Sorry for the lack of contact - things got busy! I did end up getting a new RS232 adapter, but I haven't actually had a chance to try it out yet. Will give it another shot soon, and let you know! Quote
AJB2K3 Posted Sunday at 05:39 AM Posted Sunday at 05:39 AM (edited) I changed my adapter, moved back to raw python and sent 0xFE 0x00 0x00 0xFF but got back 0x00 Before on the pl2303 adapter I was just getting b\'' I cant find the opp/bytecodes in NQC, can someone send me the link to them please? I've also loopback tested all my cables and they work, its just sorting out coms. Edited Sunday at 06:16 AM by AJB2K3 Quote
BrickTronic Posted Sunday at 06:50 PM Posted Sunday at 06:50 PM (edited) 13 hours ago, AJB2K3 said: I changed my adapter, moved back to raw python and sent 0xFE 0x00 0x00 0xFF but got back 0x00 Before on the pl2303 adapter I was just getting b\'' I cant find the opp/bytecodes in NQC, can someone send me the link to them please? I've also loopback tested all my cables and they work, its just sorting out coms. Hello, Did you also send unlock after power-up and periodic "Alive" ? And does you Toggle Command when sent miltiple time in sequence ? 3 9 13 17 23 29 34 39 45 51 57 62 68 74 80 86 92 98 104 109 115 120 126 132 138 144 150 156 162 167 173 178 184 190 196 202 208 214 220 226 232 237 243 248 254 259 265 271 277 283 289 295 301 306 312 318 324 329 335 341 347 0xFE 0x00 0x00 0xFF 0xA5 0x5A 0x44 0xBB 0x6F 0x90 0x20 0xDF 0x79 0x86 0x6F 0x90 0x75 0x8A 0x20 0xDF 0x62 0x9D 0x79 0x86 0x74 0x8B 0x65 0x9A 0x2C 0xD3 0x20 0xDF 0x77 0x88 0x68 0x97 0x65 0x9A 0x6E 0x91 0x20 0xDF 0x49 0xB6 0x20 0xDF 0x6B 0x94 0x6E 0x91 0x6F 0x90 0x63 0x9C 0x6B 0x94 0x3F 0xC0 0x85 0x7A #NV D o y o u b y t e , w h e n I k n o c k ? 3 9 14 20 25 31 37 43 49 55 61 67 72 78 83 89 94 100 105 111 117 123 129 135 140 146 152 158 164 170 176 182 187 193 199 205 211 217 223 229 234 240 245 251 257 263 269 275 280 286 292 298 303 309 315 320 326 331 337 342 348 354 360 365 371 376 382 388 393 399 404 0xFF 0x5A 0xA5 0x4A 0xB5 0x75 0x8A 0x73 0x8C 0x74 0x8B 0x20 0xDF 0x61 0x9E 0x20 0xDF 0x62 0x9D 0x69 0x96 0x74 0x8B 0x20 0xDF 0x6F 0x90 0x66 0x99 0x66 0x99 0x20 0xDF 0x74 0x8B 0x68 0x97 0x65 0x9A 0x20 0xDF 0x62 0x9D 0x6C 0x93 0x6F 0x90 0x63 0x9C 0x6B 0x94 0x21 0xDE 0xE8 0x17 0xFF 0x46 0xB9 0x46 0xB9 0xFF 0xEF 0x10 0xEF 0x10 0xFF 0xB5 0x4A 0xB5 0x4A #NV J u s t a b i t o f f t h e b l o c k ! 177 Set power down delay (minutes) 231 Alive 66 Set sensor mode (sensor, code) where code=mode,slope Documentation on available Opcodes are in the SDK Package available at Philo's Page (it is a selfextracting EXE-File) Inside this Zip-Container there is File RCX2 LASM byte codes.pdf in Folder .\L EGOMindstormsSDK25.exe\\program files\LEGO\LEGO Mindstorms SDK\Doc\ Without Unlock Sequence after Cybermaster Power-On no communicatiion passible. when Alive not received periodically, loss of communication (Time-Out -> Watch-Dog) Jo Edited Sunday at 07:10 PM by BrickTronic Add Hint Quote
AJB2K3 Posted Sunday at 06:55 PM Posted Sunday at 06:55 PM Hmm gemini is loosing patience with this now. import serial import time PORT = '/dev/cu.usbserial-24110' # Update this to your port def send_nqc_style(ser, channel, opcode, data=[]): # 1. Prepare Inner RF Data with Complements # Every byte (opcode, data, and inner sum) is followed by its NOT inner_raw = [opcode] + data inner_sum = sum(inner_raw) & 0xFF rf_body = [] for b in inner_raw + [inner_sum]: rf_body.append(b) rf_body.append(b ^ 0xFF) # Complement # 2. Add Channel (usually not complemented) full_payload = [channel] + rf_body # 3. Calculate Outer Tower Checksum # Tower logic: Sum includes the Length byte + the payload length_byte = len(full_payload) outer_sum = (length_byte + sum(full_payload)) & 0xFF # 4. Construct Final Frame packet = [0x02, length_byte] + full_payload + [outer_sum, 0x03] print(f"\nTX: {bytes(packet).hex(' ')}") ser.write(bytes(packet)) time.sleep(0.6) # Required for RF turnaround if ser.in_waiting > 0: res = ser.read(ser.in_waiting) print(f"RX: {res.hex(' ')}") return res print("RX: [No Response - Brick didn't reply]") return None try: ser = serial.Serial(PORT, 2400, parity=serial.PARITY_ODD, timeout=2) # Critical: The CyberMaster often ignores commands unless a # 'Keep Alive' or 'Link' has been established recently. print("--- Polling Battery (The 'NQC' Way) ---") # Expected TX for Opcode 0x10: 02 05 00 10 ef 10 ef fd 03 send_nqc_style(ser, 0, 0x10) time.sleep(1) print("\n--- Sending Beep ---") # 0x51 is beep, 0x02 is the sound type send_nqc_style(ser, 0, 0x51, [0x02]) ser.close() except Exception as e: print(f"Error: {e}") this python code causes the brick to flash in receiving but the function calls don't work. Quote
Toastie Posted Sunday at 07:48 PM Posted Sunday at 07:48 PM 46 minutes ago, BrickTronic said: Without Unlock Sequence after Cybermaster Power-On no communicatiion passible. when Alive not received periodically, loss of communication (Time-Out -> Watch-Dog) I saw exactly the same behavior: No unlocking, no communication (LEDs blinking or not is not any sign of logical communication. The tower LED blinks regardless which bytes are fed to it. Sometimes the CM brick's LED flashes, but no true communication. My test for a known good CM brick: I use BricxCC to unlock the CM brick (this way, you get a visual confirmation in the IDE that "the link" is established, then end BricxCC, then use a terminal program on the same port, and then manually send commands for some time. I believe sending a command also resets the time-out counter on the CM brick. 52 minutes ago, BrickTronic said: Toggle Command Equally important: When sending, e.g., "beep" repeatedly, you need to flip the toggle bit each time. Or, just send another command; the next beep can then be identical to the first beep. If that works, then I know that tower+CM brick are actually working. Regards, Thorsten Quote
AJB2K3 Posted Sunday at 08:15 PM Posted Sunday at 08:15 PM 1 hour ago, BrickTronic said: Hello, Did you also send unlock after power-up and periodic "Alive" ? And does you Toggle Command when sent miltiple time in sequence ? 3 9 13 17 23 29 34 39 45 51 57 62 68 74 80 86 92 98 104 109 115 120 126 132 138 144 150 156 162 167 173 178 184 190 196 202 208 214 220 226 232 237 243 248 254 259 265 271 277 283 289 295 301 306 312 318 324 329 335 341 347 0xFE 0x00 0x00 0xFF 0xA5 0x5A 0x44 0xBB 0x6F 0x90 0x20 0xDF 0x79 0x86 0x6F 0x90 0x75 0x8A 0x20 0xDF 0x62 0x9D 0x79 0x86 0x74 0x8B 0x65 0x9A 0x2C 0xD3 0x20 0xDF 0x77 0x88 0x68 0x97 0x65 0x9A 0x6E 0x91 0x20 0xDF 0x49 0xB6 0x20 0xDF 0x6B 0x94 0x6E 0x91 0x6F 0x90 0x63 0x9C 0x6B 0x94 0x3F 0xC0 0x85 0x7A #NV D o y o u b y t e , w h e n I k n o c k ? 3 9 14 20 25 31 37 43 49 55 61 67 72 78 83 89 94 100 105 111 117 123 129 135 140 146 152 158 164 170 176 182 187 193 199 205 211 217 223 229 234 240 245 251 257 263 269 275 280 286 292 298 303 309 315 320 326 331 337 342 348 354 360 365 371 376 382 388 393 399 404 0xFF 0x5A 0xA5 0x4A 0xB5 0x75 0x8A 0x73 0x8C 0x74 0x8B 0x20 0xDF 0x61 0x9E 0x20 0xDF 0x62 0x9D 0x69 0x96 0x74 0x8B 0x20 0xDF 0x6F 0x90 0x66 0x99 0x66 0x99 0x20 0xDF 0x74 0x8B 0x68 0x97 0x65 0x9A 0x20 0xDF 0x62 0x9D 0x6C 0x93 0x6F 0x90 0x63 0x9C 0x6B 0x94 0x21 0xDE 0xE8 0x17 0xFF 0x46 0xB9 0x46 0xB9 0xFF 0xEF 0x10 0xEF 0x10 0xFF 0xB5 0x4A 0xB5 0x4A #NV J u s t a b i t o f f t h e b l o c k ! 177 Set power down delay (minutes) 231 Alive 66 Set sensor mode (sensor, code) where code=mode,slope Documentation on available Opcodes are in the SDK Package available at Philo's Page (it is a selfextracting EXE-File) Inside this Zip-Container there is File RCX2 LASM byte codes.pdf in Folder .\L EGOMindstormsSDK25.exe\\program files\LEGO\LEGO Mindstorms SDK\Doc\ Without Unlock Sequence after Cybermaster Power-On no communicatiion passible. when Alive not received periodically, loss of communication (Time-Out -> Watch-Dog) Jo I'm on OSX, cant extract .exe's. Quote
Toastie Posted Sunday at 08:40 PM Posted Sunday at 08:40 PM 22 minutes ago, AJB2K3 said: I'm on OSX, cant extract .exe's. Would a zip file do? If so, here's a link to my universities cloud server - the file is the exe Jo referenced, stored as zip file: https://uni-wuppertal.sciebo.de/s/ebemboGYrrimRWk Best Thorsten Quote
AJB2K3 Posted Monday at 07:36 AM Posted Monday at 07:36 AM 10 hours ago, Toastie said: Would a zip file do? If so, here's a link to my universities cloud server - the file is the exe Jo referenced, stored as zip file: https://uni-wuppertal.sciebo.de/s/ebemboGYrrimRWk Best Thorsten Thanks dude. Quote
AJB2K3 Posted Monday at 08:38 AM Posted Monday at 08:38 AM (edited) Update Managed to get the Cybermaster brick's LED to flash with: import serial import time PORT = '' def sweep_channels(ser): # We use the Opcode 0x10 (Battery Poll) because it's proven to work. # We will try Channel 0 (A6), Channel 1 (A7), and Channel 2 (A8). # Math: Length(05) + Sync + Opcode(10) + Op_Comp(EF) + Opcode(10) + Op_Comp(EF) channels = { "Ch 0 (A6)": 0xA6, "Ch 1 (A7)": 0xA7, "Ch 2 (A8)": 0xA8 } for name, sync in channels.items(): # Calculating checksum: (Length + Sync + 10 + EF + 10 + EF) # Note: 10+EF = FF. So: 05 + Sync + FF + FF checksum = (0x05 + sync + 0xFF + 0xFF) & 0xFF packet = bytes([0x02, 0x05, sync, 0x10, 0xEF, 0x10, 0xEF, checksum, 0x03]) print(f"--- Testing {name} ---") print(f"TX: {packet.hex(' ')}") ser.reset_input_buffer() ser.write(packet) time.sleep(0.5) if ser.in_waiting > 0: res = ser.read(ser.in_waiting).hex(' ') print(f"RX: {res}") else: print("RX: [Accepted]") time.sleep(1.0) # Gap to let the Brick reset try: ser = serial.Serial(PORT, 2400, parity=serial.PARITY_ODD, timeout=2) sweep_channels(ser) ser.close() except Exception as e: print(f"Error: {e}") Edited Monday at 10:02 AM by AJB2K3 Quote
Toastie Posted Monday at 09:38 AM Posted Monday at 09:38 AM 59 minutes ago, AJB2K3 said: Cybermaster brick to flash What does that mean? Flashing as it turns its LED on and off (but that is it), or actually executing a command? Best Thorsten Quote
AJB2K3 Posted Monday at 10:01 AM Posted Monday at 10:01 AM 22 minutes ago, Toastie said: What does that mean? Flashing as it turns its LED on and off (but that is it), or actually executing a command? Best Thorsten When the green light flashes it means its received the transmission. Quote
AJB2K3 Posted Monday at 10:42 AM Posted Monday at 10:42 AM Ok we have the Cybermaster brick receiving now continuously but it just flashes 3 times when a command is sent to the motors. Quote
Toastie Posted Monday at 01:46 PM Posted Monday at 01:46 PM Does it play sounds? Does it activate the third output? CMs are known to have bad motors - the disc magnets inside regularly went bad. Do your wheels spin freely (or with the resistance of a good geared down motor? I have 5 CM bricks of which 1 + 1/2 is working motorwise. Everything else is fine (communication, memory=programming, 3rd output). Best Thorsten Quote
AJB2K3 Posted Monday at 02:08 PM Posted Monday at 02:08 PM (edited) 29 minutes ago, Toastie said: Does it play sounds? Does it activate the third output? CMs are known to have bad motors - the disc magnets inside regularly went bad. Do your wheels spin freely (or with the resistance of a good geared down motor? I have 5 CM bricks of which 1 + 1/2 is working motorwise. Everything else is fine (communication, memory=programming, 3rd output). Best Thorsten the CM's use the MK2A and 2B 9V motors which are prone to failure and both my modules had a failed motor (thankfully on opposite sides). NO, I think its in command mode 5 flashes instead of 3 after receiving a message but still trying to get the motors running. Triggers acceptance flash but no motors or beeps. import serial import time PORT = '/dev/cu.usbserial-24110' def nqc_force_drive(ser): # The header that is currently giving you 5 flashes header = bytes([0x02, 0x05, 0x00, 0x10, 0xEF, 0x10, 0xEF, 0xFD, 0x03]) sync = bytes([0xA5, 0x5A]) # 1. Set Power B to 7 (22 DD 07 F8) set_pwr = bytes([0x22, 0xDD, 0x07, 0xF8]) # 2. Motor B ON + Forward (21 DE 81 7E) # This is the bitmask that bridges the 7.2V rail to the motor pins. drive_fwd = bytes([0x21, 0xDE, 0x81, 0x7E]) print("--- 5-Flash State Active: Forcing H-Bridge Engagement ---") try: # We flood this to 'latch' the state before the watchdog times out for _ in range(50): ser.write(header + sync + set_pwr + sync + drive_fwd) time.sleep(0.04) except KeyboardInterrupt: pass try: ser = serial.Serial(PORT, 2400, parity=serial.PARITY_ODD, timeout=0.1) nqc_force_drive(ser) ser.close() except Exception as e: print(f"Error: {e}") Edited Monday at 02:16 PM by AJB2K3 Quote
Toastie Posted 19 hours ago Posted 19 hours ago 22 hours ago, AJB2K3 said: Triggers acceptance flash but no motors or beeps. So you do the initialization by sending the appropriate bytes, right? And then you send a motor command, the brick replies by flashing its LED 3 times, correct? I just got put my CMs + RF tower: Using BricxCC, upon pressing "find brick", the Tower LED flashes briefly, then again, then for maybe a second, then 3 times briefly. The CM bricks replies 2 times with 5 flashes each. Now, I am believing to recall that whenever the tower sends out certain commands, a reply is expected. The incoming reply is indicated by the second flash of the tower LED and by the 5 flashes on the CM brick. So what I believe is happening upon establishing a connection is sending a byte code, get the reply, send the unlocking string, get a reply. Furthermore, I can't confirm the necessity of sending repeated "keep alive" messages on short time scales (that was the case with Interface B): In BricxCC I set the power down time of the CM brick to 15 min. Then sent a motor A on command, then unplugged the RF tower from the USB2Ser adapter, waited for a couple of minutes, plugged it in again, sent the motor A sop command - works. The power down time is reset to 15 min upon receiving a new command. Regards Thorsten Quote
HughC Posted 4 hours ago Posted 4 hours ago Hello @AJB2K3, an interesting project! The bytes you're sending don't look quite right, but hopefully that will be easy to fix. The RCX2 LASM byte codes document Thorsten shared should be quite helpful, if a bit overwhelming at first. Page 5 has this snippet about the opcode bytes: Byte code command structure The virtual machine executes byte commands following the general pattern: Opcode byte Parameter bytes… X X X X T N N N ... The ‘T’ field is for flow control (a ‘toggle’ bit) – re-sent commands keep the bit whereas new commands will toggle it to indicate that something new was send and that it should be executed. The combination ‘X X X X N N N’ is the actual byte code. The ’N N N’ (the three lowest bits – 3 LSB) tells how many parameter bytes to expect after the opcode1. This is useful if commands intended for another type of P-brick was accidentally sent – if the command is not recognised, the interpreter can skip past it. 1 For program size efficiency, the (unused) lenghts 6 and 7 actually means 0 and 1 respectively. It doubles the number of available commands with few parameters. Checking the bytes your code is sending, that isn't getting followed. For example, set_pwr = bytes([0x22, 0xDD, 0x07, 0xF8]) 0x22 has 010 as the low three bits, so should be followed by two parameter bytes. Also, checking the LASM byte codes list, 0x22 is SetWatch, the two parameters are the hours and the minutes to show on the RCX's LCD. I'm not sure how the Cybermaster would handle that? Motors can be a bit tricky, both given the way so many get stuck, and given how many variables (power, direction, on/off/brake) you need to set to get one turning. I went with sound in my experiments because it is simple - 0x51 0x00 plays sound 1, 0x51 0x05 plays sound 6. (0x51 is PlaySystemSound, the 1 byte following is the sound number to play.) To get it to actually run command 0x51 0x05, there is a bit more to do. The header needs to be added - that's 0xFE 0x00 0x00 0xFF. You need to keep track of a toggle bit, and swap that every command. If the toggle bit needs to be 1, then add 8 to the command. 0x51 becomes 0x59 every second time you send it. Only poll, command 0x10, does not need the toggle bit flipped, but you can if you want. If you don't toggle the toggle bit, the brick will ignore you. You then need to calculate a checksum, by adding the command and all parameter bytes together. 0x51 + 0x05 gives a checksum of 0x56. (Or 0x5E if the toggle is set). If the checksum ends up higher than 0xFF, AND it with 0xFF. If the checksum doesn't match, the brick will also ignore the message I think? Then, you need to calculate the complement of every command, parameter and checksum byte. The complement of 0x51 0x05 0x56 would be 0xAE 0xFA 0xA9, and when merged in that gives a packet of 0x51 0xAE 0x05 0xFA 0x56 0xA9. Putting all of that together, to play sound 6, you would need to send the header, the command and its complement, any parameters and their complements, and the checksum and its complement, as @BrickTronic posted above in the Command Frame table column. So you would send 0xFE 0x00 0x00 0xFF 0x51 0xAE 0x05 0xFA 0x56 0xA9. This is assuming that the brick is unlocked. An RCX will just accept commands from the moment it is turned on (provided it has firmware loaded), but the Cybermaster needs a bit more to be sent the unlock command 0xA5. Command 0xA5 doesn't follow the normal rule about parameter bytes, it has a lot more. The parameter bytes for 0xA5 are the ASCII values for "Do you byte, when I knock?". Add in the checksum, then the complements of everything, and send that. From BricxCC's log, that starts with FE 00 00 FF A5 5A 44 BB 6F 90 20 DF 79 86 6F 90 75 8A 20 DF 62. (In that, we can see the header 0xFE 0x00 0x00 0xFF, the command 0xA5 and its complement, then the parameter bytes 0x44 0x6F 0x20 0x79 0x6F 0x75 0x20 0x62 which are "Do you b". The rest of the message follows the same pattern, more parameter bytes for the rest of the string and their complements, then the checksum). Hopefully that helps a bit? Once the brick is beeping reliably, then your fun with motors can begin. (If you do need to replace a stuffed motor, internally the Cybermaster motors are identical to 71427 motors. I took a good magnet from a 71427 with a broken output axle to fix my Cybermaster.) Quote
AJB2K3 Posted 29 minutes ago Posted 29 minutes ago 3 hours ago, HughC said: Hello @AJB2K3, an interesting project! The bytes you're sending don't look quite right, but hopefully that will be easy to fix. The RCX2 LASM byte codes document Thorsten shared should be quite helpful, if a bit overwhelming at first. Page 5 has this snippet about the opcode bytes: Byte code command structure The virtual machine executes byte commands following the general pattern: Opcode byte Parameter bytes… X X X X T N N N ... The ‘T’ field is for flow control (a ‘toggle’ bit) – re-sent commands keep the bit whereas new commands will toggle it to indicate that something new was send and that it should be executed. The combination ‘X X X X N N N’ is the actual byte code. The ’N N N’ (the three lowest bits – 3 LSB) tells how many parameter bytes to expect after the opcode1. This is useful if commands intended for another type of P-brick was accidentally sent – if the command is not recognised, the interpreter can skip past it. 1 For program size efficiency, the (unused) lenghts 6 and 7 actually means 0 and 1 respectively. It doubles the number of available commands with few parameters. Checking the bytes your code is sending, that isn't getting followed. For example, set_pwr = bytes([0x22, 0xDD, 0x07, 0xF8]) 0x22 has 010 as the low three bits, so should be followed by two parameter bytes. Also, checking the LASM byte codes list, 0x22 is SetWatch, the two parameters are the hours and the minutes to show on the RCX's LCD. I'm not sure how the Cybermaster would handle that? Motors can be a bit tricky, both given the way so many get stuck, and given how many variables (power, direction, on/off/brake) you need to set to get one turning. I went with sound in my experiments because it is simple - 0x51 0x00 plays sound 1, 0x51 0x05 plays sound 6. (0x51 is PlaySystemSound, the 1 byte following is the sound number to play.) To get it to actually run command 0x51 0x05, there is a bit more to do. The header needs to be added - that's 0xFE 0x00 0x00 0xFF. You need to keep track of a toggle bit, and swap that every command. If the toggle bit needs to be 1, then add 8 to the command. 0x51 becomes 0x59 every second time you send it. Only poll, command 0x10, does not need the toggle bit flipped, but you can if you want. If you don't toggle the toggle bit, the brick will ignore you. You then need to calculate a checksum, by adding the command and all parameter bytes together. 0x51 + 0x05 gives a checksum of 0x56. (Or 0x5E if the toggle is set). If the checksum ends up higher than 0xFF, AND it with 0xFF. If the checksum doesn't match, the brick will also ignore the message I think? Then, you need to calculate the complement of every command, parameter and checksum byte. The complement of 0x51 0x05 0x56 would be 0xAE 0xFA 0xA9, and when merged in that gives a packet of 0x51 0xAE 0x05 0xFA 0x56 0xA9. Putting all of that together, to play sound 6, you would need to send the header, the command and its complement, any parameters and their complements, and the checksum and its complement, as @BrickTronic posted above in the Command Frame table column. So you would send 0xFE 0x00 0x00 0xFF 0x51 0xAE 0x05 0xFA 0x56 0xA9. This is assuming that the brick is unlocked. An RCX will just accept commands from the moment it is turned on (provided it has firmware loaded), but the Cybermaster needs a bit more to be sent the unlock command 0xA5. Command 0xA5 doesn't follow the normal rule about parameter bytes, it has a lot more. The parameter bytes for 0xA5 are the ASCII values for "Do you byte, when I knock?". Add in the checksum, then the complements of everything, and send that. From BricxCC's log, that starts with FE 00 00 FF A5 5A 44 BB 6F 90 20 DF 79 86 6F 90 75 8A 20 DF 62. (In that, we can see the header 0xFE 0x00 0x00 0xFF, the command 0xA5 and its complement, then the parameter bytes 0x44 0x6F 0x20 0x79 0x6F 0x75 0x20 0x62 which are "Do you b". The rest of the message follows the same pattern, more parameter bytes for the rest of the string and their complements, then the checksum). Hopefully that helps a bit? Once the brick is beeping reliably, then your fun with motors can begin. (If you do need to replace a stuffed motor, internally the Cybermaster motors are identical to 71427 motors. I took a good magnet from a 71427 with a broken output axle to fix my Cybermaster.) I thought I read somewhere that it it still used the handshake. Thanks, for pointing to the document and the clues. Unfortunately spent all last night rebuilding the IDE after a typo in the RCX's sensor read function broke everything (yes user error because of dyslexia) Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.