Moshiboard: Difference between revisions

The educational technology and digital learning wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
Line 14: Line 14:
Like many different boards there is some light swizzling for some bytes in this case the command bytes are swizzled. Half of the command byte has random data (random distribution) and the other half is control code. This gives us 4 bits of command code, 4 random bytes. The swizzling can actually thus be interpreted in several ways, but we'll put the first four bits as command and the last 4 bits as random.
Like many different boards there is some light swizzling for some bytes in this case the command bytes are swizzled. Half of the command byte has random data (random distribution) and the other half is control code. This gives us 4 bits of command code, 4 random bytes. The swizzling can actually thus be interpreted in several ways, but we'll put the first four bits as command and the last 4 bits as random.


# 0A 0E 1A 1E 4A 4E 51 53 59 5A 5B 5E 71 74 79 7B
The algorithm from unswizzled to swizzled form is:
# 00 01 03 04 09 0C 10 14 21 23 29 2B 40 44 50 54
# 55 57 5D 5F 75 77 7D 7F 8A 8E 9A 9E CA CE DA DE
# 05 07 0D 0F 25 27 2D 2F 80 84 90 94 C0 C4 D0 D4
# AA AE BA BE D5 D7 DD DF EA EE F5 F7 FA FD FE FF
# 15 17 1D 1F 35 37 3D 3F 88 8C 98 9C C8 CC D8 DC
# 45 47 4D 4F 65 67 6D 6F 82 86 92 96 C2 C6 D2 D6
# A2 A6 B2 B6 C5 C7 CD CF E2 E5 E6 E7 ED EF F2 F6
 
These are the 8 different code seen, in their 16 different forms. If we apply a swizzle to these:


     def swizzle(b, b0, b1, b2, b3, b4, b5, b6, b7):
     def swizzle(b, b0, b1, b2, b3, b4, b5, b6, b7):
Line 37: Line 28:
             return swizzle(q, 5, 1, 7, 2, 4, 3, 6, 0)
             return swizzle(q, 5, 1, 7, 2, 4, 3, 6, 0)


# ['50', '51', '52', '53', '54', '55', '56', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f', '8e']
Note that each lowest bit triggers a different type of swizzle. So every other bit is swizzled in a different form. The last bit remains in the same position in both so these different swizzles perfectly intermingle.
# ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0c', '0d', '0e', '0f', '18']
# ['70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f']
# ['20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f']
# ['f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff']
# ['30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f']
# ['60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f']
# ['e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef']


=== Inverted Swizzling ===
=== Swizzle LUT ===


{| class="wikitable"
{| class="wikitable"
Line 83: Line 67:
|-
|-
| 0xF? || 0xaa || 0xd5 || 0xea || 0xd7 || 0xba || 0xf5 || 0xfa || 0xf7 || 0xae || 0xdd || 0xee || 0xdf || 0xbe || 0xfd || 0xfe || 0xff
| 0xF? || 0xaa || 0xd5 || 0xea || 0xd7 || 0xba || 0xf5 || 0xfa || 0xf7 || 0xae || 0xdd || 0xee || 0xdf || 0xbe || 0xfd || 0xfe || 0xff
|-
|}
All commands will be referenced by the first 4 bits. The remaining 4 bits fit a random distribution.


|}


== Moshiboard Commands ==
== Moshiboard Commands ==
Line 94: Line 81:
! Command !! Length !! Code !! Parameters
! Command !! Length !! Code !! Parameters
|-
|-
| Cut_XY_ABS || 1 || 0xF? || (2 byte ABS X) (2 byte ABS Y)
| 2nd CMD For Jump  || 0 || 0x0? || (2 bytes) (2 bytes) (2 bytes)
|-
| UNKNOWN || 1 || 0x1? || unknown
|-
|-
| Cut_X_ABS || 1 || 0xE? || (2 byte ABS X)
| Terminal Commands || 1 || 0x2? || nothing. (occurs in 6 bytes increments)
|-
|-
| UNKNOWN || 1 || 0xD? || unknown
| Move_Y_ABS || 1 || 0x3? || (2 byte ABS Y)
|-
|-
| UNKNOWN || 1 || 0xC? || unknown
| UNKNOWN || 1 || 0x4? || unknown
|-
|-
| Cut_Y_ABS || 1 || 0xB? || (2 byte ABS Y)
| Header Start || 1 || 0x5? || (2 bytes unknown)
|-
|-
| UNKNOWN || 1 || 0xA? || unknown
| Move_X_ABS || 1 || 0x6? || (2 byte ABS X)
|-
|-
| UNKNOWN || 1 || 0x9? || unknown
| Move_XY_ABS || 1 || 0x7? || (2 byte ABS X) (2 byte ABS Y)
|-
|-
| UNKNOWN || 1 || 0x8? || unknown
| UNKNOWN || 1 || 0x8? || unknown
|-
|-
| Move_XY_ABS || 1 || 0x7? || (2 byte ABS X) (2 byte ABS Y)
| UNKNOWN || 1 || 0x9? || unknown
|-
|-
| Move_X_ABS || 1 || 0x6? || (2 byte ABS X)
| UNKNOWN || 1 || 0xA? || unknown
|-
|-
| Header Start || 1 || 0x5? || (2 bytes unknown)
| Cut_Y_ABS || 1 || 0xB? || (2 byte ABS Y)
|-
|-
| UNKNOWN || 1 || 0x4? || unknown
| UNKNOWN || 1 || 0xC? || unknown
|-
|-
| Move_Y_ABS || 1 || 0x3? || (2 byte ABS Y)
| UNKNOWN || 1 || 0xD? || unknown
|-
|-
| Terminal Commands || 1 || 0x2? || nothing. (occurs in 6 bytes increments)
| Cut_X_ABS || 1 || 0xE? || (2 byte ABS X)
|-
|-
| UNKNOWN || 1 || 0x1? || unknown
| Cut_XY_ABS || 1 || 0xF? || (2 byte ABS X) (2 byte ABS Y)
|-
| 2nd Command For Jump  || 0 || 0x0? || (2 bytes) (2 bytes) (2 bytes)
|-
|-
|}
|}


Bitwise this implies our flags for our 4 data bytes are: Laser, X-Value, Unknown, Y-Value
Bitwise this implies our flags for our 4 data bytes are: Laser, X-Value, Unknown, Y-Value

Latest revision as of 06:35, 4 August 2020

Moshiboard

The Moshiboard laser cutter board is a proprietary controller with proprietary software. In the case of Moshiboard this software is called `MoshiDraw`. Like most proprietary laser cutting software intended for a specific board it has significant disadvantages and the only open source solutions are attempts at reverse engineering.

USB Protocol

The USB plug on the board is connected directly to the CH341A communications chip and configured in parallel port (EPP19) mode. This gives it the same Vendor id and product id as other things like the M2 Nano.

The usb device is located at vendor 0x1a86 with a PID of 0x5512


Swizzling

Like many different boards there is some light swizzling for some bytes in this case the command bytes are swizzled. Half of the command byte has random data (random distribution) and the other half is control code. This gives us 4 bits of command code, 4 random bytes. The swizzling can actually thus be interpreted in several ways, but we'll put the first four bits as command and the last 4 bits as random.

The algorithm from unswizzled to swizzled form is:

   def swizzle(b, b0, b1, b2, b3, b4, b5, b6, b7):
       return ((b >> 0) & 1) << b7 | ((b >> 1) & 1) << b6 | \
              ((b >> 2) & 1) << b5 | ((b >> 3) & 1) << b4 | \
              ((b >> 4) & 1) << b3 | ((b >> 5) & 1) << b2 | \
              ((b >> 6) & 1) << b1 | ((b >> 7) & 1) << b0
   def convert(q):
       if q & 1:
           return swizzle(q, 7, 6, 2, 4, 3, 5, 1, 0)
       else:
           return swizzle(q, 5, 1, 7, 2, 4, 3, 6, 0)

Note that each lowest bit triggers a different type of swizzle. So every other bit is swizzled in a different form. The last bit remains in the same position in both so these different swizzles perfectly intermingle.

Swizzle LUT

CMD 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F
0x0? 0x00 0x01 0x40 0x03 0x10 0x21 0x50 0x23 0x04 0x09 0x44 0x0b 0x14 0x29 0x54 0x2b
0x1? 0x08 0x11 0x48 0x13 0x18 0x31 0x58 0x33 0x0c 0x19 0x4c 0x1b 0x1c 0x39 0x5c 0x3b
0x2? 0x80 0x05 0xc0 0x07 0x90 0x25 0xd0 0x27 0x84 0x0d 0xc4 0x0f 0x94 0x2d 0xd4 0x2f
0x3? 0x88 0x15 0xc8 0x17 0x98 0x35 0xd8 0x37 0x8c 0x1d 0xcc 0x1f 0x9c 0x3d 0xdc 0x3f
0x4? 0x02 0x41 0x42 0x43 0x12 0x61 0x52 0x63 0x06 0x49 0x46 0x4b 0x16 0x69 0x56 0x6b
0x5? 0x0a 0x51 0x4a 0x53 0x1a 0x71 0x5a 0x73 0x0e 0x59 0x4e 0x5b 0x1e 0x79 0x5e 0x7b
0x6? 0x82 0x45 0xc2 0x47 0x92 0x65 0xd2 0x67 0x86 0x4d 0xc6 0x4f 0x96 0x6d 0xd6 0x6f
0x7? 0x8a 0x55 0xca 0x57 0x9a 0x75 0xda 0x77 0x8e 0x5d 0xce 0x5f 0x9e 0x7d 0xde 0x7f
0x8? 0x20 0x81 0x60 0x83 0x30 0xa1 0x70 0xa3 0x24 0x89 0x64 0x8b 0x34 0xa9 0x74 0xab
0x9? 0x28 0x91 0x68 0x93 0x38 0xb1 0x78 0xb3 0x2c 0x99 0x6c 0x9b 0x3c 0xb9 0x7c 0xbb
0xA? 0xa0 0x85 0xe0 0x87 0xb0 0xa5 0xf0 0xa7 0xa4 0x8d 0xe4 0x8f 0xb4 0xad 0xf4 0xaf
0xB? 0xa8 0x95 0xe8 0x97 0xb8 0xb5 0xf8 0xb7 0xac 0x9d 0xec 0x9f 0xbc 0xbd 0xfc 0xbf
0xC? 0x22 0xc1 0x62 0xc3 0x32 0xe1 0x72 0xe3 0x26 0xc9 0x66 0xcb 0x36 0xe9 0x76 0xeb
0xD? 0x2a 0xd1 0x6a 0xd3 0x3a 0xf1 0x7a 0xf3 0x2e 0xd9 0x6e 0xdb 0x3e 0xf9 0x7e 0xfb
0xE? 0xa2 0xc5 0xe2 0xc7 0xb2 0xe5 0xf2 0xe7 0xa6 0xcd 0xe6 0xcf 0xb6 0xed 0xf6 0xef
0xF? 0xaa 0xd5 0xea 0xd7 0xba 0xf5 0xfa 0xf7 0xae 0xdd 0xee 0xdf 0xbe 0xfd 0xfe 0xff

All commands will be referenced by the first 4 bits. The remaining 4 bits fit a random distribution.


Moshiboard Commands

Since command bytes have 4 bits there can only be 16 of them.

Command Length Code Parameters
2nd CMD For Jump 0 0x0? (2 bytes) (2 bytes) (2 bytes)
UNKNOWN 1 0x1? unknown
Terminal Commands 1 0x2? nothing. (occurs in 6 bytes increments)
Move_Y_ABS 1 0x3? (2 byte ABS Y)
UNKNOWN 1 0x4? unknown
Header Start 1 0x5? (2 bytes unknown)
Move_X_ABS 1 0x6? (2 byte ABS X)
Move_XY_ABS 1 0x7? (2 byte ABS X) (2 byte ABS Y)
UNKNOWN 1 0x8? unknown
UNKNOWN 1 0x9? unknown
UNKNOWN 1 0xA? unknown
Cut_Y_ABS 1 0xB? (2 byte ABS Y)
UNKNOWN 1 0xC? unknown
UNKNOWN 1 0xD? unknown
Cut_X_ABS 1 0xE? (2 byte ABS X)
Cut_XY_ABS 1 0xF? (2 byte ABS X) (2 byte ABS Y)

Bitwise this implies our flags for our 4 data bytes are: Laser, X-Value, Unknown, Y-Value

Reverse engineering resources.

Links

Official

Other Sources