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