text: import os
  from datetime import datetime
  
  def build(parent):
  	board = '7i97'
  	halFilePath = os.path.join(parent.configPath, parent.configNameUnderscored + '.hal')
  	parent.machinePTE.appendPlainText(f'Building {halFilePath}')
  
  	halContents = []
  	halContents = ['# This file was created with the 7i97 Configuration Tool on ']
  	halContents.append(datetime.now().strftime('%b %d %Y %H:%M:%S') + '\n')
  	halContents.append('# If you make changes to this file DO NOT run the configuration tool again!\n')
  	halContents.append('# This file will be replaced with a new file if you do!\n\n')
  
  	# build the standard header
  	halContents.append('# kinematics\n')
  	halContents.append('loadrt [KINS]KINEMATICS\n\n')
  	halContents.append('# motion controller\n')
  	halContents.append('loadrt [EMCMOT]EMCMOT ')
  	halContents.append('servo_period_nsec=[EMCMOT]SERVO_PERIOD ')
  	halContents.append('num_joints=[KINS]JOINTS\n\n')
  	halContents.append('# hostmot2 driver\n')
  	halContents.append('loadrt hostmot2\n\n')
  	halContents.append('loadrt hm2_eth ')
  	halContents.append('board_ip=[HOSTMOT2](IPADDRESS) ')
  	halContents.append('config="num_encoders=6 num_pwmgens=6 num_stepgens=0 sserial_port_0=00xxxxxx"')
  	halContents.append(f'\nsetp hm2_{board}.0.watchdog.timeout_ns {parent.servoPeriodSB.value() * 5}\n')
  
  	halContents.append('# standard components\n')
  	halContents.append(f'loadrt pid num_chan={parent.axes + 1} \n\n')
  
  	halContents.append('\n# Threads\n')
  	halContents.append(f'addf hm2_{board}.0.read servo-thread\n')
  	halContents.append('addf motion-command-handler servo-thread\n')
  	halContents.append('addf motion-controller servo-thread\n')
  	halContents.append(f'setp hm2_{board}.0.dpll.01.timer-us -100\n')
  
  	halContents.append('\n# Input Scan Time setup\n')
  	halContents.append(f'setp hm2_{board}.0.inmux.00.slow_scans [INPUTS]SLOW_SCANS\n')
  	halContents.append(f'setp hm2_{board}.0.inmux.00.fast_scans [INPUTS]FAST_SCANS\n')
  	# hm2_7i97.0.inmux.00.slow_scans hm2_7i97.0.inmux.00.fast_scans
  
  	for i in range(parent.axes + 1):
  		halContents.append(f'addf pid.{i}.do-pid-calcs servo-thread\n')
  	halContents.append(f'addf hm2_{board}.0.write servo-thread\n')
  
  	halContents.append('\n# Global PWM setup\n')
  	halContents.append(f'setp hm2_{board}.0.pwmgen.pwm_frequency 48000\n')
  
  
  	for i in range(parent.axes):
  		halContents.append(f'\n# Joint {i}\n')
  		halContents.append(f'setp pid.{i}.Pgain [JOINT_{i}]P\n')
  		halContents.append(f'setp pid.{i}.Igain [JOINT_{i}]I\n')
  		halContents.append(f'setp pid.{i}.Dgain [JOINT_{i}]D\n')
  		halContents.append(f'setp pid.{i}.bias [JOINT_{i}]BIAS\n')
  		halContents.append(f'setp pid.{i}.FF0 [JOINT_{i}]FF0\n')
  		halContents.append(f'setp pid.{i}.FF1 [JOINT_{i}]FF1\n')
  		halContents.append(f'setp pid.{i}.FF2 [JOINT_{i}]FF2\n')
  		halContents.append(f'setp pid.{i}.deadband [JOINT_{i}]DEADBAND\n')
  		halContents.append(f'setp pid.{i}.maxoutput [JOINT_{i}]MAX_OUTPUT\n')
  		halContents.append(f'setp pid.{i}.maxerror [JOINT_{i}]MAX_ERROR\n')
  		halContents.append(f'setp pid.{i}.error-previous-target true\n\n')
  
  		halContents.append('\n# joint enable chain\n')
  		halContents.append(f'net joint-{i}-index-enable <=> pid.{i}.index-enable\n')
  		halContents.append(f'net joint-{i}-enable => pid.{i}.enable\n')
  		halContents.append(f'net joint-{i}-enable => hm2_{board}.0.pwmgen.0{i}.enable\n')
  
  		halContents.append('\n# position command and feedback\n')
  		halContents.append(f'net joint-{i}-pos-cmd => pid.{i}.command\n')
  		halContents.append(f'net joint-{i}-pos-fb => pid.{i}.feedback\n')
  		halContents.append(f'net joint-{i}-output <= pid.{i}.output\n')
  
  		halContents.append('\n# PWM setup\n')
  		halContents.append(f'setp hm2_{board}.0.pwmgen.00.output-type 1 #PWM pin0\n')
  		halContents.append(f'setp hm2_{board}.0.pwmgen.00.offset-mode 1 # offset mode so 50% = 0\n')
  		halContents.append(f'setp hm2_{board}.0.pwmgen.00.scale [JOINT_0]SCALE\n')
  
  		halContents.append('\n# Encoder Setup\n')
  		halContents.append(f'setp hm2_{board}.0.encoder.0{i}.scale  [JOINT_0]ENCODER_SCALE\n')
  		halContents.append(f'setp hm2_{board}.0.encoder.0{i}.counter-mode 0\n')
  		halContents.append(f'setp hm2_{board}.0.encoder.0{i}.filter 1\n')
  		halContents.append(f'setp hm2_{board}.0.encoder.0{i}.index-invert 0\n')
  		halContents.append(f'setp hm2_{board}.0.encoder.0{i}.index-mask 0\n')
  		halContents.append(f'setp hm2_{board}.0.encoder.0{i}.index-mask-invert 0\n')
  
  		halContents.append('\n# Position Command and Feedback\n')
  		halContents.append(f'net joint-{i}-fb <= hm2_{board}.0.encoder.0{i}.position\n')
  		#halContents.append(f'net joint-{i}-output => hm2_{board}.0.{card}.0.{port}.analogout{i}\n')
  		halContents.append(f'net joint-{i}-pos-cmd <= joint.{i}.motor-pos-cmd\n')
  
  	if parent.spindleTypeCB.itemData(parent.spindleTypeCB.currentIndex()):
  		halContents.append('\n# Spindle\n')
  		s = parent.axes
  		halContents.append(f'setp pid.{s}.Pgain [SPINDLE]P\n')
  		halContents.append(f'setp pid.{s}.Igain [SPINDLE]I\n')
  		halContents.append(f'setp pid.{s}.Dgain [SPINDLE]D\n')
  		halContents.append(f'setp pid.{s}.bias [SPINDLE]BIAS\n')
  		halContents.append(f'setp pid.{s}.FF0 [SPINDLE]FF0\n')
  		halContents.append(f'setp pid.{s}.FF1 [SPINDLE]FF1\n')
  		halContents.append(f'setp pid.{s}.FF2 [SPINDLE]FF2\n')
  		halContents.append(f'setp pid.{s}.deadband [SPINDLE]DEADBAND\n')
  		halContents.append(f'setp pid.{s}.maxoutput [SPINDLE]MAX_OUTPUT\n')
  		halContents.append(f'setp pid.{s}.error-previous-target true\n')
  		halContents.append('setp setp hm2_7i97.0.pwmgen.pwm_frequency [SPINDLE]PWM_FREQUENCY\n')
  		halContents.append('setp hm2_7i97.0.pwmgen.00.scale [SPINDLE]SCALE\n')
  
  		halContents.append(f'net spindle-index-enable <=> pid.{s}.index-enable\n')
  		halContents.append(f'net spindle-on pid.{s}.enable\n')
  		halContents.append(f'net spindle-vel-cmd-rpm => pid.{s}.command\n')
  		halContents.append(f'net spindle-vel-fb-rpm => pid.{s}.feedback\n')
  		halContents.append(f'net spindle-output <= pid.{s}.output\n')
  		halContents.append('net spindle-output => hm2_7i97.0.pwmgen.00.value\n')
  		halContents.append('\n# Spindle Velocity Pins\n')
  		halContents.append('net spindle-vel-cmd-rps <=  spindle.0.speed-out-rps\n')
  		halContents.append('net spindle-vel-cmd-rps-abs <= spindle.0.speed-out-rps-abs\n')
  		halContents.append('net spindle-vel-cmd-rpm <= spindle.0.speed-out\n')
  		halContents.append('net spindle-vel-cmd-rpm-abs <= spindle.0.speed-out-abs\n')
  
  		halContents.append('\n# Spindle Command Pins\n')
  		halContents.append('net spindle-on => hm2_7i97.0.pwmgen.00.enable\n')
  
  		halContents.append('net spindle-on <= spindle.0.on\n')
  		halContents.append('net spindle-cw <= spindle.0.forward\n')
  		halContents.append('net spindle-ccw <= spindle.0.reverse\n')
  		halContents.append('net spindle-brake <= spindle.0.brake\n')
  		halContents.append('net spindle-revs => spindle.0.revs\n')
  		halContents.append('net spindle-at-speed => spindle.0.at-speed\n')
  		halContents.append('net spindle-vel-fb-rps => spindle.0.speed-in\n')
  		halContents.append('net spindle-index-enable => spindle.0.index-enable\n')
  		halContents.append('\n# Set spindle at speed signal\n')
  		halContents.append('sets spindle-at-speed true\n')
  		halContents.append('\n')
  
  	externalEstop = False
  	for i in range(6): # test for an external e stop input
  		key = getattr(parent, 'inputPB_' + str(i)).text()
  		if key == 'External E Stop':
  			externalEstop = True
  	if not externalEstop:
  		halContents.append('\n# Standard I/O Block - EStop, Etc\n')
  		halContents.append('# create a signal for the estop loopback\n')
  		halContents.append('net estop-loopback iocontrol.0.emc-enable-in <= iocontrol.0.user-enable-out\n')
  
  	if parent.manualToolChangeCB.isChecked():
  		halContents.append('\n#  Manual Tool Change Dialog\n')
  
  		halContents.append('loadusr -W hal_manualtoolchange\n')
  		halContents.append('net tool-change-request    =>  hal_manualtoolchange.change\n')
  		halContents.append('net tool-change-confirmed  <=  hal_manualtoolchange.changed\n')
  		halContents.append('net tool-number            =>  hal_manualtoolchange.number\n')
  
  		halContents.append('\n# create signals for tool loading loopback\n')
  		halContents.append('net tool-prep-loop iocontrol.0.tool-prepare => iocontrol.0.tool-prepared\n')
  		halContents.append('net tool-change-loop iocontrol.0.tool-change => iocontrol.0.tool-changed\n')
  
  	if parent.ladderGB.isChecked():
  		halContents.append('\n# # Load Classicladder without GUI\n')
  		# this line needs to be built from the options if any are above 0
  		ladderOptions = []
  		for option in parent.ladderOptionsList:
  			if getattr(parent, option).value() > 0:
  				ladderOptions.append(getattr(parent, option).property('option') + '=' + str(getattr(parent, option).value()))
  		if ladderOptions:
  				halContents.append(f'loadrt classicladder_rt {" ".join(ladderOptions)}\n')
  		else:
  			halContents.append('loadrt classicladder_rt\n')
  		halContents.append('addf classicladder.0.refresh servo-thread 1\n')
  
  	try:
  		with open(halFilePath, 'w') as halFile:
  			halFile.writelines(halContents)
  	except OSError:
  		parent.machinePTE.appendPlainText(f'OS error\n {traceback.print_exc()}')
  