LMCV4-FIBER-M: Difference between revisions

The educational technology and digital learning wiki
Jump to navigation Jump to search
(Added additional background information)
 
(7 intermediate revisions by the same user not shown)
Line 3: Line 3:
== Reverse engineering ==
== Reverse engineering ==


The reverse engineering of the product has been done (at least initially) https://www.bryce.pw/engraver.html
The reverse engineering of the product has been done (at least initially) https://www.bryce.pw/engraver.html and Jason Dorie (https://lightburn.fider.io/) the latter for inclusion in LightBurn, a highly regarded software program within the laser community.


Command codes are 2 bytes 16 bit little-endian numbers these starting either with high or low bit (0x00 or 0x80) depending on whether it is a commandList command or a single command. In the larger LMC Ezcad3 code set these can sometimes be reach into the first byte when the code value exceeds 255 0xFF. The board communications are done through a simple USB connection with several endpoints connecting to:
Command codes are 2 bytes 16 bit little-endian numbers these starting either with high or low bit (0x00 or 0x80) depending on whether it is a commandList command or a single command. In the larger LMC Ezcad3 code set these can sometimes reach into the first byte when the code value exceeds 255 0xFF. The board communications are done through a simple USB connection with several endpoints connecting to:


idVendor=0x9588, idProduct=0x9899
idVendor=0x9588, idProduct=0x9899


Commands are sent and received in the clear without swizzling or additional bits.
* ep_hodi = 0x01  # endpoint for the "dog," i.e. dongle.
* ep_hido = 0x81  # fortunately it turns out that we can ignore it completely.
* ep_homi = 0x02  # endpoint for host out, machine in. (query status, send ops)
* ep_himo = 0x88  # endpoint for host in, machine out. (receive status reports)
 
Commands are sent and received in the clear without swizzling or additional control bits.


== commandList codes: ==
== commandList codes: ==


0x800d is called in listJumpTo
{| class="wikitable"
 
|+
0x8001 is called in listJumpTo
! command code
 
! name
0x8005 is called in listMarkTo
! notes
 
! usage
0x8003 is called in listLaserOnPoint
|-
 
| 0x800d  
0x8006 is called in listJumpSpeed
| listJumpTo
 
|
0x800c is called in listMarkSpeed
|
 
|-
0x801b is called in listMarkFreq (if lasertype == 3)
| 0x8001  
 
| listJumpTo
0x800a is called in listMarkFreq (if lasertype == 4)
|
 
|-
0x800b is called in listMarkFreq  (if lasertype == 4  and 0x800a returned 0).
| 0x8005
 
| listMarkTo
0x8013 is called in listMarkFreq (if some_setting2 == 0)
|
 
|
0x800a is called in listMarkFreq (if some_setting3 != 0)
|-
 
| 0x8003
0x8012 is called in listMarkPowerRatio
listLaserOnPoint
 
|
0x800b is called in listMarkPowerRatio (if lasertype == 0 (CO2))
|
 
|-
0x800b is called in listMarkPulseWidth
| 0x8006  
 
| listJumpSpeed
0x8026 is called in listIPGYLPMPulseWidth
|
 
|
0x8007 is called in listLaserOnDelay
|-
 
| 0x800c  
0x8008 is called in listLaserOffDelay
| listMarkSpeed
 
|
0x800f is called in listPolygonDelay
|
 
|-
0x8004 is called in listMarkEndDelay
| 0x801b  
 
| listMarkFreq  
0x8004 is called in listDelayTime
| (if lasertype == 3)
 
|
0x8004 is called in listDelayTimeUs
|-
 
| 0x800a  
0x8002 is called in listEndofList
| listMarkFreq
 
| (if lasertype == 4)
0x801a is called in listFlyEnable
|-
 
| 0x800b
0x801d is called in listFlyDelay
| listMarkFreq 
 
| (if lasertype == 4  and 0x800a returned 0).
0x8011 is called in listWritrPort
|
 
|-
0x8051 is called in ReadyMark
| 0x8013
 
| listMarkFreq
0x8002 is called in Run.
| (if some_setting2 == 0)
 
|
0x801c is called in listDirectLaserSwitch
|-
 
| 0x800a  
0x801e is called in SetCo2FPK
| listMarkFreq
 
| (if some_setting3 != 0)
0x8005 is called in listDirectMarkTo
|
 
|-
0x801f is called in lsFlyWaitInput
| 0x8012  
 
| listMarkPowerRatio
0x8021 is called in listIPGOpenMO
|
 
|
0x8023 is called in listChangeMarkCount
|-
 
| 0x800b  
0x8022 is called in listWaitForInput
| listMarkPowerRatio
 
| (if lasertype == 0 (CO2))
0x8026 is called in listIPGSetConfigExtend
|
 
|-
0x8028 is called in listFlyEncoderCount
| 0x800b  
 
| listMarkPulseWidth
0x8029 is called in listSetDaZWord (if this returns 0, listDelayTime is called)
|
 
|
0x8050 is called in listJptSetParam
|-
 
| 0x8026  
0x8025 is called in listEnableWeldPowerWave
| listIPGYLPMPulseWidth
 
|
0x8024 is called in listSetWeldPowerWave
|
 
|-
0x8006 is called in ScanBmpPtBuf (several times)
| 0x8007  
 
| listLaserOnDelay
== Single Commands: ==
|
 
|
Single commands are 12 bytes long in 6 2-byte words of little-endian command codes. Some commands in the DLC ezcad3 codeset move into 0x01xx range, nothing here appears to. These commands are usually followed by GetState which reads 6 bytes of data. This provides response information and state information. These do not use all six bytes to send every command many are padded with zeros.
|-
 
| 0x8008  
DisableLaser 0x2 -- all zero
| listLaserOffDelay
 
|
EnableLaser 0x4 --  all zero
|
 
|-
ExecuteList 0x5 --  all zero
| 0x800f  
 
| listPolygonDelay
GetVersion 0x7 -- 1, 0 0 0
|
 
|
GetSerialNo 0x9 -- all zero
|-
 
| 0x8004  
GetListStatus 0xa -- all zero
| listMarkEndDelay
 
|
GetPositionXY 0xc -- all zero
|-
 
| 0x8004
GotoXY 0xd --  variable, stack value, 0 0
| listDelayTime
 
|
LaserSignalOff 0xe -- all zero
|
 
|-
LaserSignalOn 0xf -- all zero
| 0x8004
 
| listDelayTimeUs
SetAxisMotionParam 0x26 --  variable, stack value, 0 0
|
 
|
MoveAxisTo 0x29  -- lower 8 bits, 16-24th bits specified by single variable, 0, 0
|-
 
| 0x8002  
AxisGoOrigin 0x28 -- variable, 0, 0, 0
| listEndofList
 
|
GetAxisPos 0x2a -- stack value, 0, 0, 0
|
 
|-
SetAxisOriginParam 0x27 --  variable, stack value, 0 0
| 0x801a
 
| listFlyEnable
WriteCorTable 0x15 -- boolean, 0, 0, 0
|
 
|
ResetList 0x12 -- all zero
|-
 
| 0x801d
RestartList 0x13 -- all zero
| listFlyDelay
 
|
SetControlMode 0x16 -- stack value, 0, 0, 0
|
 
|-
SetDelayMode 0x17 -- stack value, 0, 0, 0
| 0x8011
 
| listWritrPort
SetMaxPolyDelay 0x18 -- stack value, 0, 0, 0
|
 
|
SetEndOfList 0x19 -- all zero
|-
 
| 0x8051
SetFirstPulseKiller 0x1a -- stack value, 0, 0, 0
| ReadyMark
 
|
SetTiming 0x1c -- stack value, 0, 0, 0
|
 
|-
SetPwmHalfPeriod 0x1e -- stack value, 0, 0, 0
| 0x8002
 
| Run.
SetPwmPulseWidth 0x6 -- stack value, 0, 0, 0
|
 
|
SetLaserMode 0x1b -- stack value, 0, 0, 0
|-
 
| 0x801c
SetStandby 0x1d -- variable, variable, stack value, 0
| listDirectLaserSwitch
 
|
StopExecute 0x1f -- all zero
|
 
|-
StopList 0x20 -- all zero
| 0x801e
 
| SetCo2FPK
ReadPort 0x25 -- all zero
|
 
|
WritePort 0x21 - variable, stack value, 0, 0
|-
 
| 0x8005
WriteAnalogPort1 0x22 -- stack value, 0, 0, 0
|  listDirectMarkTo
 
|
WriteAnalogPort2 0x23 -- 0, stack value, 0, 0 (stack value is 2nd)
|
 
|-
WriteAnalogPortX 0x24 -- variable, stack value, 0
| 0x801f
 
| lsFlyWaitInput
SetFpkParam 0x62 -- variable, variable, variable, stack_value
|
 
|
SetFpkParam2 0x2e -- variable, variable, variable, stack_value
|-
 
| 0x8021
IPG_OpemMO 0x33 -- stack value, 0, 0, 0
| listIPGOpenMO
 
|
IPG_GETStMO_AP 0x34 -- all zero
|
 
|-
ENABLEZ 0x3a or 0x39 (if a value is zero) -- all zero
| 0x8023
 
| listChangeMarkCount
SETZDATA 0x3b variable, stack value, 0 0
|
 
|
SetSPISimmerCurrent 0x3c -- variable, stack_value
|-
| 0x8022
| listWaitForInput
|
|
|-
| 0x8026
| listIPGSetConfigExtend
|
|
|-
| 0x8028
| listFlyEncoderCount
|
|
|-
| 0x8029
| listSetDaZWord
| (if this returns 0, listDelayTime is called)
|
|-
| 0x8050
| listJptSetParam
|
|
|-
| 0x8025
| listEnableWeldPowerWave
|
|
|-
| 0x8024
|  listSetWeldPowerWave
|
|
|-
| 0x8006
| ScanBmpPtBuf
| (several times)
|
|}


GetFlyWaitCount 0x2b -- boolean, 0, 0, 0
=== Single Commands: ===


GetMarkCount 0x2d -- boolean, 0, 0, 0
Single commands are 12 bytes long in 6 int16le bytes. The first byte is the command code. Some commands in the DLC ezcad3 codeset move into higher byte. Nothing in the LMC board command set does. These commands are usually followed by GetState which reads 6 bytes of data. This provides response information and state information. These do not use all six int16le are used. The remaining ones are padded with zeros.
{| class="wikitable"
|+
! name
! command code
! parm1
! parm2
! parm3
! parm4
! parm5
! usage
|-
| DisableLaser
| 0x0002
| 0
| 0
| 0
| 0
| 0
|
|-
| EnableLaser
| 0x0004
| 0
| 0
| 0
| 0
| 0
|
|-
| ExecuteList
| 0x0005
| 0
| 0
| 0
| 0
| 0
|
|-
| GetVersion
| 0x0007
| 1
| 0
| 0
| 0
| 0
|
|-
| GetSerialNo
| 0x0009
| 0
| 0
| 0
| 0
| 0
|
|-
| GetListStatus
| 0x000a
| 0
| 0
| 0
| 0
| 0
|
|-
| GetPositionXY
| 0x000c
| 0
| 0
| 0
| 0
| 0
|
|-
| GotoXY
| 0x000d
| x
| y
| 0
| 0
| 0
|
|-
| LaserSignalOff
| 0x000e
| 0
| 0
| 0
| 0
| 0
|
|-
| LaserSignalOn
| 0x000f
| 0
| 0
| 0
| 0
| 0
|
|-
| SetAxisMotionParam
| 0x0026
| variable
| stack value
| 0
| 0
| 0
|
|-
| MoveAxisTo
| 0x0029
| lower 8 bits
| 16-24th bits
| 0
| 0
| 0
| specified by single variable
|-
| AxisGoOrigin
| 0x0028
| variable
| 0
| 0
| 0
| 0
|
|-
| GetAxisPos
| 0x002a
| stack value
| 0
| 0
| 0
| 0
|
|-
| SetAxisOriginParam
| 0x0027
| variable
| stack value
| 0
| 0
| 0
|
|-
| WriteCorTable
| 0x0015
| boolean
| 0
| 0
| 0
| 0
| This is often followed by a 8 * 63 * 63 byte xy-lookup table
|-
| ResetList
| 0x0012
| 0
| 0
| 0
| 0
| 0
|
|-
| RestartList
| 0x0013
| 0
| 0
| 0
| 0
| 0
|
|-
| SetControlMode
| 0x0016
| stack value
| 0
| 0
| 0
| 0
|
|-
| SetDelayMode
| 0x0017
| stack value
| 0
| 0
| 0
| 0
|
|-
| SetMaxPolyDelay
| 0x0018
| stack value
| 0
| 0
| 0
| 0
|
|-
| SetEndOfList
| 0x0019
| 0
| 0
| 0
| 0
| 0
|
|-
| SetFirstPulseKiller
| 0x001a
| stack value
| 0
| 0
| 0
| 0
|
|-
| SetTiming
| 0x001c
| stack value
| 0
| 0
| 0
| 0
|
|-
| SetPwmHalfPeriod
| 0x001e
| stack value
| 0
| 0
| 0
| 0
|
|-
| SetPwmPulseWidth
| 0x0006
| stack value
| 0
| 0
| 0
| 0
|
|-
| SetLaserMode
| 0x001b
| stack value
| 0
| 0
| 0
| 0
|
|-
| SetStandby
| 0x001d
| variable
| variable
| stack value
| 0
| 0
|
|-
| StopExecute
| 0x001f
| 0
| 0
| 0
| 0
| 0
|
|-
| StopList
| 0x0020
| 0
| 0
| 0
| 0
| 0
|
|-
| ReadPort
| 0x0025
| 0
| 0
| 0
| 0
| 0
|
|-
| WritePort
| 0x0021
| variable
| stack value
| 0
| 0
| 0
|
|-
| WriteAnalogPort1
| 0x0022
| stack value
| 0
| 0
| 0
| 0
|
|-
| WriteAnalogPort2
| 0x0023
| 0
| stack value
| 0
| 0
| 0
|
|-
| WriteAnalogPortX
| 0x0024
| variable
| stack value
| 0
| 0
| 0
|
|-
| SetFpkParam
| 0x0062
| variable
| variable
| variable
| stack_value
| 0
| Probably First Pulse Killer
|-
| SetFpkParam2
| 0x002e
| variable
| variable
| variable
| stack_value
| 0
|
|-
| IPG_OpemMO
| 0x0033
| stack value
| 0
| 0
| 0
| 0
|
|-
| IPG_GETStMO_AP
| 0x0034
| 0
| 0
| 0
| 0
| 0
|
|-
| ENABLEZ
| 0x003a
| 0
| 0
| 0
| 0
| 0
|
|-
| ENABLEZ-alt
| 0x0039
| 0
| 0
| 0
| 0
| 0
| (used if a value is zero)
|-
| SETZDATA
| 0x003b
| variable
| stack value
| 0
| 0
| 0
|
|-
| SetSPISimmerCurrent
| 0x003c
| variable
| stack_value
| 0
| 0
| 0
|
|-
| GetFlyWaitCount
| 0x002b
| boolean
| 0
| 0
| 0
| 0
|
|-
| GetMarkCount
| 0x002d
| boolean
| 0
| 0
| 0
| 0
|
|}


== IOCLT control codes ==
== IOCLT control codes ==

Latest revision as of 14:39, 11 January 2022

JCZ LMCV4-FIBER-M is a fiber galvo type laser controlled by Ezcad 2, the LMC boards are all controlled by Ezcad2. The board controls a galvo head laser through the standard XY-100 protocol on a DB25 connection. The board itself costs around $200 USD (Jan 2022). With the similar protocol Ezcad 3 board going for $800 USD (Jan 2022). The additional features of the Ezcad3 are likely not worth the value. The reason why people pay for them is so that they can use Ezcad3 rather than being stuck to using Ezcad2 which like a lot of laser software is disliked by users. In the case of Ezcad, it crashes often and the F1 let me see what my design is doing is right next to the F2 burn the project without the lining up the material buttons. There are some hacked versions of this software which provide dongle-less support and raises the ram limit which is baked into the ram starved program.

Reverse engineering

The reverse engineering of the product has been done (at least initially) https://www.bryce.pw/engraver.html and Jason Dorie (https://lightburn.fider.io/) the latter for inclusion in LightBurn, a highly regarded software program within the laser community.

Command codes are 2 bytes 16 bit little-endian numbers these starting either with high or low bit (0x00 or 0x80) depending on whether it is a commandList command or a single command. In the larger LMC Ezcad3 code set these can sometimes reach into the first byte when the code value exceeds 255 0xFF. The board communications are done through a simple USB connection with several endpoints connecting to:

idVendor=0x9588, idProduct=0x9899

  • ep_hodi = 0x01 # endpoint for the "dog," i.e. dongle.
  • ep_hido = 0x81 # fortunately it turns out that we can ignore it completely.
  • ep_homi = 0x02 # endpoint for host out, machine in. (query status, send ops)
  • ep_himo = 0x88 # endpoint for host in, machine out. (receive status reports)

Commands are sent and received in the clear without swizzling or additional control bits.

commandList codes:

command code name notes usage
0x800d listJumpTo
0x8001 listJumpTo
0x8005 listMarkTo
0x8003 listLaserOnPoint
0x8006 listJumpSpeed
0x800c listMarkSpeed
0x801b listMarkFreq (if lasertype == 3)
0x800a listMarkFreq (if lasertype == 4)
0x800b listMarkFreq  (if lasertype == 4  and 0x800a returned 0).
0x8013 listMarkFreq (if some_setting2 == 0)
0x800a listMarkFreq (if some_setting3 != 0)
0x8012 listMarkPowerRatio
0x800b listMarkPowerRatio (if lasertype == 0 (CO2))
0x800b listMarkPulseWidth
0x8026 listIPGYLPMPulseWidth
0x8007 listLaserOnDelay
0x8008 listLaserOffDelay
0x800f listPolygonDelay
0x8004 listMarkEndDelay
0x8004 listDelayTime
0x8004 listDelayTimeUs
0x8002 listEndofList
0x801a listFlyEnable
0x801d listFlyDelay
0x8011 listWritrPort
0x8051 ReadyMark
0x8002 Run.
0x801c listDirectLaserSwitch
0x801e SetCo2FPK
0x8005 listDirectMarkTo
0x801f lsFlyWaitInput
0x8021 listIPGOpenMO
0x8023 listChangeMarkCount
0x8022 listWaitForInput
0x8026 listIPGSetConfigExtend
0x8028 listFlyEncoderCount
0x8029 listSetDaZWord (if this returns 0, listDelayTime is called)
0x8050 listJptSetParam
0x8025 listEnableWeldPowerWave
0x8024 listSetWeldPowerWave
0x8006 ScanBmpPtBuf (several times)

Single Commands:

Single commands are 12 bytes long in 6 int16le bytes. The first byte is the command code. Some commands in the DLC ezcad3 codeset move into higher byte. Nothing in the LMC board command set does. These commands are usually followed by GetState which reads 6 bytes of data. This provides response information and state information. These do not use all six int16le are used. The remaining ones are padded with zeros.

name command code parm1 parm2 parm3 parm4 parm5 usage
DisableLaser 0x0002 0 0 0 0 0
EnableLaser 0x0004 0 0 0 0 0
ExecuteList 0x0005 0 0 0 0 0
GetVersion 0x0007 1 0 0 0 0
GetSerialNo 0x0009 0 0 0 0 0
GetListStatus 0x000a 0 0 0 0 0
GetPositionXY 0x000c 0 0 0 0 0
GotoXY 0x000d x y 0 0 0
LaserSignalOff 0x000e 0 0 0 0 0
LaserSignalOn 0x000f 0 0 0 0 0
SetAxisMotionParam 0x0026 variable stack value 0 0 0
MoveAxisTo 0x0029 lower 8 bits 16-24th bits 0 0 0 specified by single variable
AxisGoOrigin 0x0028 variable 0 0 0 0
GetAxisPos 0x002a stack value 0 0 0 0
SetAxisOriginParam 0x0027 variable stack value 0 0 0
WriteCorTable 0x0015 boolean 0 0 0 0 This is often followed by a 8 * 63 * 63 byte xy-lookup table
ResetList 0x0012 0 0 0 0 0
RestartList 0x0013 0 0 0 0 0
SetControlMode 0x0016 stack value 0 0 0 0
SetDelayMode 0x0017 stack value 0 0 0 0
SetMaxPolyDelay 0x0018 stack value 0 0 0 0
SetEndOfList 0x0019 0 0 0 0 0
SetFirstPulseKiller 0x001a stack value 0 0 0 0
SetTiming 0x001c stack value 0 0 0 0
SetPwmHalfPeriod 0x001e stack value 0 0 0 0
SetPwmPulseWidth 0x0006 stack value 0 0 0 0
SetLaserMode 0x001b stack value 0 0 0 0
SetStandby 0x001d variable variable stack value 0 0
StopExecute 0x001f 0 0 0 0 0
StopList 0x0020 0 0 0 0 0
ReadPort 0x0025 0 0 0 0 0
WritePort 0x0021 variable stack value 0 0 0
WriteAnalogPort1 0x0022 stack value 0 0 0 0
WriteAnalogPort2 0x0023 0 stack value 0 0 0
WriteAnalogPortX 0x0024 variable stack value 0 0 0
SetFpkParam 0x0062 variable variable variable stack_value 0 Probably First Pulse Killer
SetFpkParam2 0x002e variable variable variable stack_value 0
IPG_OpemMO 0x0033 stack value 0 0 0 0
IPG_GETStMO_AP 0x0034 0 0 0 0 0
ENABLEZ 0x003a 0 0 0 0 0
ENABLEZ-alt 0x0039 0 0 0 0 0 (used if a value is zero)
SETZDATA 0x003b variable stack value 0 0 0
SetSPISimmerCurrent 0x003c variable stack_value 0 0 0
GetFlyWaitCount 0x002b boolean 0 0 0 0
GetMarkCount 0x002d boolean 0 0 0 0

IOCLT control codes

And additionally there are calls to a couple different IO events:

See winsdk-7 header file https://github.com/tpn/winsdk-7/blob/master/v7.1A/Include/WinIoCtl.h

MIO_Cmd uses the dwIoControlCode 0x99982014

MIO_GetState uses: 0x99982010

MIO_NewCmd uses: 0x99982024

MIO_Reset uses: 0x99982008

MIO_WriteCmdBuf uses: 0x99982018

MIO_TransferDataZ uses: 0x99982020

MIO_ReadEpprom uses: 0x99982080

MIO_ReadAllEpprom uses: 0x99982090

MIO_ModifyEpprom uses: 0x99982088

MIO_EarseEpprom(sic) uses: 0x9998208c

MIO_WriteEpprom uses: 0x99982084

MIO_EppromSetMark uses: 0x99982094

MIO_EppromGetMark uses: 0x99982098

MIO_EppromSetTimeStamp uses: 0x9998209c

MIO_Verify uses: 0x99982028

MIO_WriteNxp uses: 0x999820c0

MIO_ReadNxp uses: 0x999820c4

External Links