/ docs / src / hal / basic-hal.txt
basic-hal.txt
  1  [[cha:basic-hal-reference]]
  2  
  3  = Basic HAL Reference
  4  
  5  This document provides a reference to the basics of HAL.
  6  
  7  [[sec:hal-commands]]
  8  == HAL Commands 
  9  
 10  More detailed information can be found in the man page for halcmd: run
 11  'man halcmd' in a terminal window.
 12  
 13  To see the HAL configuration and check the status of pins and parameters
 14  use the HAL Configuration window on the Machine menu in AXIS. To watch
 15  a pin status open the Watch tab and click on each pin you wish to watch
 16  and it will be added to the watch window.
 17  
 18  .HAL Configuration Window
 19  
 20  image::images/HAL_Configuration.png[align="center", alt="HAL Configuration Window"]
 21  
 22  === loadrt
 23  
 24  The command 'loadrt' loads a real time HAL component. Real time
 25  component functions need to be added to a thread to be updated at the
 26  rate of the thread. You cannot load a user space component into the
 27  real time space.
 28  
 29  The syntax and an example:
 30  
 31  ----
 32  loadrt <component> <options>
 33  
 34  loadrt mux4 count=1
 35  ----
 36  
 37  === addf
 38  
 39  Adds function 'functname' to thread 'threadname'. Default is to add the function
 40  in the order they are in the file. If 'position' is specified, adds the function
 41  to that spot in the thread. Negative 'position' means position with respect to
 42  the end of the thread. For example '1' is start of thread, '-1' is the end of
 43  the thread, '-3' is third from the end.
 44  
 45  Some functions it is important to load them in a certain order like the parport
 46  read and write functions. The function name is usually the the component name
 47  plus a number. In the following example the component 'or2' is loaded and 'show
 48  function' shows the name of the or2 function
 49  
 50  ----
 51  $ halrun
 52  halcmd: loadrt or2
 53  halcmd: show function
 54  Exported Functions:
 55  Owner   CodeAddr  Arg       FP   Users  Name
 56   00004  f8bc5000  f8f950c8  NO       0   or2.0
 57  ----
 58  
 59  You have to add a function from a HAL real time component to a thread
 60  to get the function to update at the rate of the thread.
 61  
 62  Usually there are two threads as shown in this example. Some components use
 63  floating point math and must be added to a thread that supports floating point
 64  math. The 'FP' indicates if floating point math is supported in that thread.
 65  
 66  ----
 67  $ halrun
 68  halcmd: loadrt motmod base_period_nsec=55555 servo_period_nsec=1000000 num_joints=3
 69  halcmd: show thread
 70  Realtime Threads:
 71       Period  FP     Name               (     Time, Max-Time )
 72       995976  YES          servo-thread (        0,        0 )
 73        55332  NO            base-thread (        0,        0 )
 74  ----
 75  
 76   - base-thread (the high-speed thread): this thread handles items that
 77     need a fast response, like making step pulses, and reading and writing
 78     the parallel port. Does not support floating point math.
 79   - servo-thread (the slow-speed thread): this thread handles items that
 80     can tolerate a slower response, like the motion controller,    ClassicLadder,
 81     and the motion command handler and supports floating point math.
 82  
 83  The syntax and an example:
 84  
 85  ----
 86  addf <function> <thread>
 87  
 88  addf mux4.0 servo-thread
 89  ----
 90  
 91  === loadusr
 92  
 93  The command 'loadusr' loads a user space HAL component. User space
 94  programs are their own separate processes, which optionally talk to
 95  other HAL components via pins and parameters. You cannot load real time
 96  components into user space.
 97  
 98  Flags may be one or more of the following:
 99  
100  [horizontal]
101  -W:: to wait for the component to become ready. The component is assumed to
102      have the same name as the first argument of the command.
103  
104  -Wn <name>:: to wait for the component, which will have the given <name>.
105      This only applies if the component has a name option.
106  
107  -w:: to wait for the program to exit
108  
109  -i:: to ignore the program return value (with -w)
110  
111  -n:: name a component when it is a valid option for that component.
112  
113  The syntax and examples:
114  
115  ----
116  loadusr <component> <options>
117  
118  loadusr halui
119  
120  loadusr -Wn spindle gs2_vfd -n spindle
121  ----
122  
123  In English it means 'loadusr wait for name spindle component gs2_vfd name spindle'.
124  
125  [[sub:net]] (((net)))
126  
127  === net
128  
129  The command 'net' creates a 'connection' between a signal and one
130  or more pins. If the signal does not exist net creates the new signal.
131  This replaces the need to use the command newsig. The optional direction
132  arrows '<=', '=>' and '<=>' make it easier to follow the logic when reading
133  a 'net' command line and are not used by the net command. The direction arrows
134  must be separated by a space from the pin names.
135  
136  .Syntax and Example:
137  ----
138  net signal-name pin-name <optional arrow> <optional second pin-name>
139  
140  net home-x joint.0.home-sw-in <= parport.0.pin-11-in
141  ----
142  
143  In the above example 'home-x' is the signal name, 'joint.0.home-sw-in' is a
144  'Direction IN' pin, '<=' is the optional direction arrow, and 
145  'parport.0.pin-11-in' is a 'Direction OUT' pin. This may seem confusing but
146  the in and out labels for a parallel port pin indicates the physical way the
147  pin works not how it is handled in HAL.
148  
149  
150  A pin can be connected to a signal if it obeys the following rules:
151  
152  * An IN pin can always be connected to a signal
153  * An IO pin can be connected unless there's an OUT pin on the signal
154  * An OUT pin can be connected only if there are no other OUT or IO pins
155    on the signal
156  
157  The same 'signal-name' can be used in multiple net commands to connect
158  additional pins, as long as the rules above are obeyed.
159  
160  .Signal Direction
161  
162  image::images/signal-direction.png[align="center", alt="Signal Direction"]
163  
164  This example shows the signal xStep with the source being
165  stepgen.0.out and with two readers, parport.0.pin-02-out and
166  parport.0.pin-08-out. Basically the value of stepgen.0.out is sent to
167  the signal xStep and that value is then sent to parport.0.pin-02-out
168  and parport.0.pin-08-out.
169  
170  ----
171  #   signal    source            destination          destination
172  net xStep stepgen.0.out => parport.0.pin-02-out parport.0.pin-08-out
173  ----
174  
175  Since the signal xStep contains the value of stepgen.0.out (the
176  source) you can use the same signal again to send the value to another
177  reader. To do this just use the signal with the readers on another
178  line.
179  
180  ----
181  net xStep => parport.0.pin-02-out
182  ----
183  
184  .I/O pins
185  An I/O pin like encoder.N.index-enable can be read or set as allowed by the component.
186  
187  === setp
188  
189  The command 'setp' sets the value of a pin or parameter. The valid
190  values will depend on the type of the pin or parameter. It is an error
191  if the data types do not match.
192  
193  Some components have parameters that need to be set before use.
194  Parameters can be set before use or while running as needed. You cannot
195  use setp on a pin that is connected to a signal.
196  
197  The syntax and an example:
198  
199  ----
200  setp <pin/parameter-name> <value>
201  
202  setp parport.0.pin-08-out TRUE
203  ----
204  
205  === sets
206  
207  The command 'sets' sets the value of a signal.
208  
209  The syntax and an example:
210  
211  ----
212  sets <signal-name> <value>
213  
214  net mysignal and2.0.in0 pyvcp.my-led
215  
216  sets mysignal 1
217  ----
218  
219  It is an error if:
220  
221  * The signal-name does not exist
222  * If the signal already has a writer
223  * If value is not the correct type for the signal
224  
225  === unlinkp
226  
227  The command 'unlinkp' unlinks a pin from the connected signal. If no
228  signal was connected to the pin prior running the command, nothing
229  happens. The 'unlinkp' command is useful for trouble shooting.
230  
231  The syntax and an example:
232  
233  ----
234  unlinkp <pin-name>
235  
236  unlinkp parport.0.pin-02-out
237  ----
238  
239  === Obsolete Commands
240  
241  The following commands are depreciated and may be removed from future
242  versions. Any new configuration should use the <<sub:net,'net'>> command.
243  These commands are included so older configurations will still work.
244  
245  .linksp
246  
247  The command 'linksp' creates a 'connection' between a signal and one
248  pin.
249  
250  The syntax and an example:
251  
252  ----
253  linksp <signal-name> <pin-name>
254  linksp X-step parport.0.pin-02-out
255  ----
256  
257  The 'linksp' command has been superseded by the 'net' command.
258  
259  .linkps
260  
261  The command 'linkps' creates a 'connection' between one pin and one
262  signal. It is the same as linksp but the arguments are reversed.
263  
264  The syntax and an example:
265  
266  ----
267  linkps <pin-name> <signal-name>
268  
269  linkps parport.0.pin-02-out X-Step
270  ----
271  
272  The 'linkps' command has been superseded by the 'net' command.
273  
274  .newsig
275  
276  the command 'newsig' creates a new HAL signal by the name <signame>
277  and the data type of <type>. Type must be 'bit', 's32', 'u32' or
278  'float'. Error if <signame> all ready exists.
279  
280  The syntax and an example:
281  
282  ----
283  newsig <signame> <type>
284  
285  newsig Xstep bit
286  ----
287  
288  More information can be found in the HAL manual or the man pages for
289  halrun.
290  
291  [[sec:hal-data]]
292  
293  == HAL Data
294  
295  === Bit (((Bit)))
296  
297  A bit value is an on or off.
298  
299   - bit values = true or 1 and false or 0 (True, TRUE, true are all valid)
300  
301  === Float (((Float)))
302  
303  A 'float' is a floating point number. In other words the decimal point
304  can move as needed.
305  
306   - float values = a 64 bit floating point value, with approximately 53 bits of
307     resolution and over 1000 bits of dynamic range.
308  
309  For more information on floating point numbers see:
310  
311  http://en.wikipedia.org/wiki/Floating_point[http://en.wikipedia.org/wiki/Floating_point]
312  
313  === s32 (((s32)))
314  
315  An 's32' number is a whole number that can have a negative or positive
316  value.
317  
318   - s32 values = integer numbers -2147483648 to 2147483647
319  
320  === u32 (((u32)))
321  
322  A 'u32' number is a whole number that is positive only.
323  
324   - u32 values = integer numbers 0 to 4294967295
325  
326  == HAL Files
327  
328  If you used the Stepper Config Wizard to generate your config you will
329  have up to three HAL files in your config directory.
330  
331   -  my-mill.hal (if your config is named 'my-mill') This file is loaded
332     first and should not be changed if you used the Stepper Config Wizard.
333   -  custom.hal This file is loaded next and before the GUI loads. This is
334     where you put your custom HAL commands that you want loaded before the
335     GUI is loaded. 
336   -  custom_postgui.hal This file is loaded after the GUI loads. This is
337     where you put your custom HAL commands that you want loaded after the
338     GUI is loaded. Any HAL commands that use pyVCP widgets need to be
339     placed here.
340  
341  == HAL Components
342  
343  Two parameters are automatically added to each HAL component when it
344  is created. These parameters allow you to scope the execution time of a
345  component.
346  
347  +.time+(((time)))
348  
349  +.tmax+(((tmax)))
350  
351  
352  Time is the number of CPU cycles it took to execute the function.
353  
354  Tmax is the maximum number of CPU cycles it took to execute the
355  function. Tmax is a read/write parameter so the user can set it to 0 to
356  get rid of the first time initialization on the function's execution
357  time.
358  
359  == Logic Components
360  
361  HAL contains several real time logic components. Logic components
362  follow a 'Truth Table' that states what the output is for any given
363  input. Typically these are bit manipulators and follow electrical logic
364  gate truth tables.
365  
366  === and2
367  
368  The 'and2' component is a two input 'and' gate. The truth table below
369  shows the output based on each combination of input.
370  
371  Syntax
372  
373  ----
374  and2 [count=N] | [names=name1[,name2...]]
375  ----
376  
377  Functions
378  
379  and2.n
380  
381  Pins
382  
383      and2.N.in0 (bit, in)
384      and2.N.in1 (bit, in)
385      and2.N.out (bit, out)
386  
387  Truth Table
388  
389  [width="90%", options="header"]
390  |========================================
391  |in0 | in1 | out
392  |False | False | False
393  |True | False | False
394  |False | True | False
395  |True | True | True
396  |========================================
397  
398  === not
399  
400  The 'not' component is a bit inverter.
401  
402  Syntax
403  
404  ----
405  not [count=n] | [names=name1[,name2...]]
406  ----
407  
408  Functions
409  
410      not.all
411      not.n
412  
413  Pins
414  
415      not.n.in (bit, in)
416      not.n.out (bit, out)
417  
418  Truth Table
419  
420  [width="90%", options="header"]
421  |========================================
422  |in | out
423  |True | False
424  |False | True
425  |========================================
426  
427  === or2
428  
429  The 'or2' component is a two input OR gate.
430  
431  Syntax
432  
433  ----
434  or2[count=n] | [names=name1[,name2...]]
435  ----
436  
437  Functions
438  
439  +or2.n+
440  
441  Pins
442  
443      or2.n.in0 (bit, in)
444      or2.n.in1 (bit, in)
445      or2.n.out (bit, out)
446  
447  Truth Table
448  
449  [width="90%", options="header"]
450  |========================================
451  |in0 | in1 | out
452  |True | False | True
453  |True | True | True
454  |False | True | True
455  |False | False | False
456  |========================================
457  
458  === xor2
459  
460  The 'xor2' component is a two input XOR (exclusive OR)gate.
461  
462  Syntax
463  
464  ----
465  xor2[count=n] | [names=name1[,name2...]]
466  ----
467  
468  Functions
469  
470  +xor2.n+ 
471  
472  Pins
473  
474      xor2.n.in0 (bit, in)
475      xor2.n.in1 (bit, in)
476      xor2.n.out (bit, out)
477  
478  Truth Table
479  
480  [width="90%", options="header"]
481  |========================================
482  |in0 | in1 | out
483  |True | False | True
484  |True | True | False
485  |False | True | True
486  |False | False | False
487  |========================================
488  
489  === Logic Examples
490  
491  An 'and2' example connecting two inputs to one output.
492  
493  ----
494  loadrt and2 count=1
495  
496  addf and2.0 servo-thread
497  
498  net my-sigin1 and2.0.in0 <= parport.0.pin-11-in
499  
500  net my-sigin2 and2.0.in1 <= parport.0.pin-12-in
501  
502  net both-on parport.0.pin-14-out <= and2.0.out
503  ----
504  
505  In the above example one copy of and2 is loaded into real time space
506  and added to the servo thread. Next pin 11 of the parallel port is
507  connected to the in0 bit of the and gate. Next pin 12 is connected to
508  the in1 bit of the and gate. Last we connect the and2 out bit to the
509  parallel port pin 14. So following the truth table for and2 if pin 11
510  and pin 12 are on then the output pin 14 will be on.
511  
512  == Conversion Components
513  
514  === weighted_sum
515  
516  The weighted_sum converts a group of bits to an integer. The
517  conversion is the sum of the 'weights' of the bits that are on plus any
518  offset. The weight of the m-th bit is 2^m. This is similar to a binary
519  coded decimal but with more options. The 'hold' bit stops processing the
520  input changes so the 'sum' will not change.
521  
522  The following syntax is used to load the weighted_sum component.
523  
524  ----
525  loadrt weighted_sum wsum_sizes=size[,size,...]
526  ----
527  
528  Creates weighted sum groups each with the given number of input bits
529  (size).
530  
531  To update the weighted_sum you need to attach process_wsums to a thread.
532  
533  ----
534  addf process_wsums servo-thread
535  ----
536  
537  This updates the weighted_sum component.
538  
539  In the following example clipped from the HAL Configuration window in
540  Axis the bits '0' and '2' are true and there is no offset. The 'weight'
541  of 0 is 1 and the 'weight' of 2 is 4 so the sum is 5.
542  
543  .weighted_sum
544  -----------------------------------------------------------
545  Component Pins: 
546  Owner   Type  Dir         Value  Name
547      10  bit   In           TRUE  wsum.0.bit.0.in
548      10  s32   I/O             1  wsum.0.bit.0.weight
549      10  bit   In          FALSE  wsum.0.bit.1.in
550      10  s32   I/O             2  wsum.0.bit.1.weight
551      10  bit   In           TRUE  wsum.0.bit.2.in
552      10  s32   I/O             4  wsum.0.bit.2.weight
553      10  bit   In          FALSE  wsum.0.bit.3.in
554      10  s32   I/O             8  wsum.0.bit.3.weight
555      10  bit   In          FALSE  wsum.0.hold
556      10  s32   I/O             0  wsum.0.offset
557      10  s32   Out             5  wsum.0.sum
558  -----------------------------------------------------------
559  
560