Skip to main content

Galil recently released version 1.0b of the DMC-4000 motion controller firmware. This firmware contains a new feature allowing the firmware to automatically dispatch a UDP packet signal to the host on certain events. The new feature is modeled off of the PCI interrupt signaling available on Galil PCI buses and can alert the host under 16 user defined events with the UI command and many other automatic events such as axis motion complete, digital inputs, limit switches, and position error. GalilTools provides support for this feature by displaying interrupt events in the terminal and providing the interrupt() function in the programmer's API. The firmware and software support simplifies the communication between a host PC and a DMC-4000. See EI and UI in the DMC-4000 Command Reference , and interrupt() in the GalilTools API reference.

But what about the rest of Galil's Ethernet motion Controllers, e.g. the DMC-21x3, DMC-14x5, and, even for some interrupts, the RIO? With an understanding of the UDP interrupt structure, found in the EI command in the DMC-4000 Command Reference and some manipulation of message (MG) packets, the same interrupt behavior can be made to work on non-4000 controllers.

The following code demonstrates how any Ethernet controller can be made to employ interrupts.


REM DISABLE COMPRESSION <- Do not modify line zero.  Compression must be disabled to maintain relative JS jumps

EI=65535;'interrupt mask
IM=255;'input mask

II,,IM ;'setup input interrupt for input mask
XQ#MOTCOMP,7;'run motion complete handling in last thread

c=0;'run through each of the user interrupts UI
#UILOOP
UI=c;JS(#UI+UI);'jump to UI plus offset
c=c+1
JP#UILOOP,c<16

#LOOP;'keep alive loop, automatic subs and other threads will continue to run
WT2000000000
JP#LOOP
EN

REM *** UI UDP INTERRUPT HANDLING ***
REM *************************************
REM DO NOT MODIFY CODE BLOCK
REM DO NOT CHANGE SPACING OF CODE BLOCK
REM *************************************
#UI;CW2;MG{^1},{^240},{^3}{N};CW1;EN;'UI0
CW2;MG{^1},{^241},{^3}{N};CW1;EN;'UI1
CW2;MG{^1},{^242},{^3}{N};CW1;EN;'UI2
CW2;MG{^1},{^243},{^3}{N};CW1;EN;'UI3
CW2;MG{^1},{^244},{^3}{N};CW1;EN;'UI4
CW2;MG{^1},{^245},{^3}{N};CW1;EN;'UI5
CW2;MG{^1},{^246},{^3}{N};CW1;EN;'UI6
CW2;MG{^1},{^247},{^3}{N};CW1;EN;'UI7
CW2;MG{^1},{^248},{^3}{N};CW1;EN;'UI8
CW2;MG{^1},{^249},{^3}{N};CW1;EN;'UI9
CW2;MG{^1},{^250},{^3}{N};CW1;EN;'UI10
CW2;MG{^1},{^251},{^3}{N};CW1;EN;'UI11
CW2;MG{^1},{^252},{^3}{N};CW1;EN;'UI12
CW2;MG{^1},{^253},{^3}{N};CW1;EN;'UI13
CW2;MG{^1},{^254},{^3}{N};CW1;EN;'UI14
CW2;MG{^1},{^255},{^3}{N};CW1;EN;'UI15
REM ** END UI UDP INTERRUPT HANDLING **

#POSERR
REM *** POSERR UDP INTERRUPT HANDLING ***
IF (EI & $0200) = 512 ;'if position error mask is enabled
 CW2;MG{^1},{^200},{^3}{N};CW1;'Position Error packet
 EI= (EI & $FDFF);'clear poserr bit (must be reset)
ENDIF
REM *** END POSERR UDP INTERRUPT HANDLING ***
RE1

#ININT
REM **** INPUT UDP INTERRUPT HANDLING ****
IF (EI & $8000) = 32768;' if input interrupts(UDP, not II) are enabled
 IF ((IM & 1) = 1) & (@IN[1]=0);'if  input mask is enabled, and bit is low
  CW2;MG{^1},{^225},{^3}{N};CW1;'send unique input packet
 ENDIF
 IF ((IM & 2) = 2) & (@IN[2]=0)
  CW2;MG{^1},{^226},{^3}{N};CW1
 ENDIF
 IF ((IM & 4) = 4) & (@IN[3]=0)
  CW2;MG{^1},{^227},{^3}{N};CW1
 ENDIF
 IF ((IM & 8) = 8) & (@IN[4]=0)
  CW2;MG{^1},{^228},{^3}{N};CW1
 ENDIF
 IF ((IM & 16) = 16) & (@IN[5]=0)
  CW2;MG{^1},{^229},{^3}{N};CW1
 ENDIF
 IF ((IM & 32) = 32) & (@IN[6]=0)
  CW2;MG{^1},{^230},{^3}{N};CW1
 ENDIF
 IF ((IM & 64) = 64) & (@IN[7]=0)
  CW2;MG{^1},{^231},{^3}{N};CW1
 ENDIF
 IF ((IM & 128) = 128) & (@IN[8]=0)
  CW2;MG{^1},{^232},{^3}{N};CW1
 ENDIF
 EI= (EI & $7FFF);'clear input interrupt bit (must be reset)
ENDIF
REM **** END INPUT UDP INTERRUPT HANDLING ****
 WT500;'short delay added for debounce time before returning to main code
RI

#LIMSWI
REM *** LIMSWI UDP INTERRUPT HANDLING ***
IF (EI & 1024) = 1024 ;'if limswi error mask is enabled
 CW2;MG{^1},{^192},{^3}{N};CW1;'limswi packet
 EI= (EI & $FBFF);'clear limswi bit (must be reset)
ENDIF
REM *** END LIMSWI UDP INTERRUPT HANDLING ***
WT500;'short delay added for debounce time before returning to main code
RE1

#MOTCOMP;'note, this code should run for 1-8 axes
DM scArray[8] ;'array to hold axis complete status
#MOT1
mot_c=0 ;'axis indicator, we'll process one by one for each pass
JS#MOT2 ;'we'll use the stack to recursively look at each axis
JP#MOT1 ;'recursive calls have telescoped back, start again from stack 0
'
#MOT2;' subroutine called recursively to see if up to 8 axes has completed
IF (mot_c = _BV) ;'exit condition for recursion, will only stack up # of axes
 EN ;'end the recursive stacking up
ENDIF
~h=mot_c ;'set the variable axis designator.
IF (scArray[mot_c]=1)&(_BG~h=0);'if motion has completed since last round
 JS#MOTMAP+mot_c;'dispatch UDP packet. This jump is not part of recursion.
ENDIF
scArray[mot_c]=_BG~h;'update axis status
mot_c = mot_c + 1;'increment axis indicator
JS#MOT2;'recursively call MOT2 up to eight times
EN
'
REM *** MOTION COMPLETE UDP INTERRUPT HANDLING ***
REM *************************************
REM DO NOT MODIFY CODE BLOCK
REM DO NOT CHANGE SPACING OF CODE BLOCK
REM ***********************************************
#MOTMAP;CW2;MG{^1},{^208},{^3}{N};CW1;EN
CW2;MG{^1},{^209},{^3}{N};CW1;EN
CW2;MG{^1},{^210},{^3}{N};CW1;EN
CW2;MG{^1},{^211},{^3}{N};CW1;EN
CW2;MG{^1},{^212},{^3}{N};CW1;EN
CW2;MG{^1},{^213},{^3}{N};CW1;EN
CW2;MG{^1},{^214},{^3}{N};CW1;EN
CW2;MG{^1},{^215},{^3}{N};CW1;EN
REM *** END MOTION COMPLETE INTERRUPT HANDLING ***

Naturally, the DMC code approach uses embedded program resources and won't have the same performance as a native firmware feature, but it may be just right for your application. Consult Galil's application department if you desire to have the interrupt functionality as a firmware native feature on your non-4000 controller.