# Define procs in ::scobj::xxx namespace # MakeSICSObj $obj SCT_ # The MakeSICSObj cmd adds a /sics/$obj node. NOTE the /sics node is not browsable. ## # /*-------------------------------------------------------------------------- # LF Amplifier/Generator Model AG 1010 Driver # # @file: This file contains the implementation of a driver for the AG 1010 # LF Amplifier/Generator # # @author: Jing Chen, ANSTO, 2012-06-26 # @brief: SICS driver for LF AG 1010 LF Amplifier/Generator # # ----------------------------------------------------------------------------*/ # Default AG1010 LF Amplifier/Generator Controller parameters namespace eval ::scobj::ag1010 { variable CtrlSetLIMITS [format %02x 2] variable CtrlSetPAGC [format %02x 3] variable CtrlSetPMGC [format %02x 4] variable CtrlSetFREQ [format %02x 5] variable CtrlSetSKEY [format %02x 7] variable CtrlSetBurstPar [format %02x 8] variable CtrlSetSweepPar [format %02x 9] variable CtrlGetLIMITS [format %02x 17] variable CtrlGetPAGC [format %02x 19] variable CtrlGetPMGC [format %02x 20] variable CtrlGetFREQ [format %02x 21] variable CtrlGetSKEY [format %02x 23] variable CtrlGetBurstPar [format %02x 24] variable CtrlGetSweepPar [format %02x 25] variable CtrlGetSVER [format %02x 29] variable CtrlGetMEAS [format %02x 30] variable CtrlGetSTA [format %02x 31] variable ForPowerLimit 10040 variable RefPowerLimit 1630 variable FreqUpLimit 2000000 variable FreqDownLimit 0.02 namespace export par } ############# Reading polled nodes ####################################################### ## # @brief Sends a query command to the device via a read node formalism # @param tc_root The path to the root of the node # @param nextState The next function to call after this one (typically 'rdValue' # to read the response from the device) # @param rdPara data to be sent to the device # @return nextState The next function to call after this one (typically 'rdValue') proc ::scobj::ag1010::getValue {tc_root nextState rdPara} { if {[ catch { set HEAD 0x96 set LEN [lindex $rdPara 0] set CTRL [lindex $rdPara 1] set DATA 0 set CRC 0 if {$LEN < 2} { return -code error "Error in LF AG1010 Setting: wrong data length provided." } elseif {$LEN > 2} { set cmd [format %02x%02x%02x%02x%02x $HEAD $LEN $CTRL $DATA $CRC] } else { set cmd [format %02x%02x%02x%02x $HEAD $LEN $CTRL $CRC] } sct send "$cmd" } message ]} { return -code error "Error in LF AG1010 Setting: $message." } return $nextState } ################## Writing to nodes ######################################################## ## # @brief Writes a new value to a node and sends the corresponding command to the device. # @param tc_root string variable holding the path to the object's base node in sics # @param nextState the next function to call after this one # @param wrPara indicates which control loop or which input channel the command belongs to # @return nextState Is typically noResponse as the device does not acknowledge the write request proc ::scobj::ag1010::setValue {tc_root nextState rdPara wrPara} { # tc_root and idx are not being used - however, don't remove so we can use the # same calling mask as for setPoint() or other $wrFunc variable ForPowerLimit variable RefPowerLimit variable FreqUpLimit variable FreqDownLimit set ns /sics/ag1010 #set ns [sct] if {[ catch { set HEAD 96 set LEN [lindex $rdPara 0] set CTRL [lindex $rdPara 1] set CRC 0 set newPara [string trim [sct target] " "] switch -exact $wrPara { "FPL" { if {$newPara > $ForPowerLimit || $newPara < 0} { broadcast "Error: The Limit for the Forward Power is 0~$ForPowerLimit dW" return idle } else { set RPL [hval $ns/limits/ReversePower] set data [format %04x%04x%04x%04x $newPara $RPL 0 0] } } "RPL" { if {$newPara > $RefPowerLimit || $newPara < 0} { broadcast "Error: The Limit for the Reverse Power is 0~$RefPowerLimit dW" return idle } else { set FPL [hval $ns/limits/ForwardPower] set data [format %04x%04x%04x%04x $FPL $newPara 0 0] } } "PAGC" { set data [format %04x $newPara] } "PMGC" { set data [format %04x $newPara] } "FREQ" { if {$newPara<$FreqDownLimit || $newPara>$FreqUpLimit} { broadcast "Error: Freqence shall be set between $FreqDownLimit Hz and $FreqUpLimit Hz" return idle } else { set Freq [expr $newPara / 1000] set FreqHz [expr $newPara % 1000] set data [format %04x%04x $Freq $FreqHz] } } "SoftOn" { if {$newPara > 1 || $newPara < 0} { return -code error "Error in setValue: only allowed input values for SoftKey are {0,1}." } else { if {$newPara == 1} { set data 0x80 } else { set data 0 } } if {[string match -nocase "on" [hval $ns/SKEY/Key1]]} { set data [expr $data | 0x08] } if {[string match -nocase "on" [hval $ns/SKEY/Key0]]} { set data [expr $data | 0x04] } if {[string match -nocase "on" [hval $ns/SKEY/Key2]]} { set data [expr $data | 0x02] } if {[string match -nocase "on" [hval $ns/SKEY/Key3]]} { set data [expr $data | 0x01] } set data [format %02x $data] } "Key1" { if {$newPara > 1 || $newPara < 0} { return -code error "Error in setValue: only allowed input values for Key1 are {0,1}." } else { if {$newPara == 1} { set data 0x08 } else { set data 0 } } if {[string match -nocase "Host takes" [hval $ns/SKEY/SoftOn]]} { set data [expr $data | 0x80] } if {[string match -nocase "on" [hval $ns/SKEY/Key0]]} { set data [expr $data | 0x04] } if {[string match -nocase "on" [hval $ns/SKEY/Key2]]} { set data [expr $data | 0x02] } if {[string match -nocase "on" [hval $ns/SKEY/Key3]]} { set data [expr $data | 0x01] } set data [format %02x $data] } "Key0" { if {$newPara > 1 || $newPara < 0} { return -code error "Error in setValue: only allowed input values for Key0 are {0,1}." } else { if {$newPara == 1} { set data 0x04 } else { set data 0 } } if {[string match -nocase "Host takes" [hval $ns/SKEY/SoftOn]]} { set data [expr $data | 0x80] } if {[string match -nocase "on" [hval $ns/SKEY/Key1]]} { set data [expr $data | 0x08] } if {[string match -nocase "on" [hval $ns/SKEY/Key2]]} { set data [expr $data | 0x02] } if {[string match -nocase "on" [hval $ns/SKEY/Key3]]} { set data [expr $data | 0x01] } set data [format %02x $data] } "Key2" { if {$newPara > 1 || $newPara < 0} { return -code error "Error in setValue: only allowed input values for Key2 are {0,1}." } else { if {$newPara == 1} { set data 0x02 } else { set data 0 } } if {[string match -nocase "Host takes" [hval $ns/SKEY/SoftOn]]} { set data [expr $data | 0x80] } if {[string match -nocase "on" [hval $ns/SKEY/Key1]]} { set data [expr $data | 0x08] } if {[string match -nocase "on" [hval $ns/SKEY/Key0]]} { set data [expr $data | 0x04] } if {[string match -nocase "on" [hval $ns/SKEY/Key3]]} { set data [expr $data | 0x01] } set data [format %02x $data] } "Key3" { if {$newPara > 1 || $newPara < 0} { return -code error "Error in setValue: only allowed input values for Key3 are {0,1}." } else { if {$newPara == 1} { set data 0x01 } else { set data 0 } } if {[string match -nocase "Host takes" [hval $ns/SKEY/SoftOn]]} { set data [expr $data | 0x80] } if {[string match -nocase "on" [hval $ns/SKEY/Key1]]} { set data [expr $data | 0x08] } if {[string match -nocase "on" [hval $ns/SKEY/Key0]]} { set data [expr $data | 0x04] } if {[string match -nocase "on" [hval $ns/SKEY/Key2]]} { set data [expr $data | 0x02] } set data [format %02x $data] } "BurstMode" { if {$newPara<0 || $newPara>3} { return -code error "Error in setValue: only allowed input values for BurstMode are {0,1,2,3}" } else { set BurstMode $newPara } set BRepTime [hval $ns/BurstPar/BRepTime] set TimeOfPower [hval $ns/BurstPar/TimeOfPower] set data [format %02x%04x%04x $BurstMode $BRepTime $TimeOfPower] } "BRepTime" { #set BurstMode [hval $ns/BurstPar/BurstMode] #if {[string match -nocase $BurstMode "Mode OFF"]} { # set BurstMode 0 #} elseif {[string match -nocase $BurstMode "Internal Burst"} { # set BurstMode 1 #} elseif {[string match -nocase "Without Changing" $BurstMode]} { # set BurstMode 2 #} elseif {[string match "External Burst" $BurstMode]} { # set BurstMode 3 #} else { # return -code error "Error in setValue: reading invaild BurstMode value." #} # set mode to Changing Burst Parameters without Chanigng Burst Mode -- 2 set BurstMode 2 set TimeOfPower [hval $ns/BurstPar/TimeOfPower] set data [format %02x%04x%04x $BurstMode $newPara $TimeOfPower] } "BTofP" { set BurstMode 2 set BRepTime [hval $ns/BurstPar/BRepTime] set data [format %02x%04x%04x $BurstMode $BRepTime $newPara] } "SweepMode" { if {$newPara<0 || $newPara>2} { return -code error "Error in setValue: only allowed input values for SweepMode are {0,1,2}" } else { set SweepMode $newPara } set SStr [expr [hval $ns/SweepPar/StartFreq] / 1000] set SStrHz [expr [hval $ns/SweepPar/StartFreq] % 1000] set SStp [expr [hval $ns/SweepPar/StepFreq] / 1000] set SStpHz [expr [hval $ns/SweepPar/StepFreq] % 1000] set SCyc [hval $ns/SweepPar/SCyc] set data [format %02x%02x%02x%02x%02x%02x $SweepMode $SStr $SStp $SCyc $SStrHz $SStpHz] } "SStrF" { #set SweepMode [hval $ns/SweepPar/SweepMode] #if {[string equal $SweepMode "OFF"]} { # set SweepMode 0 #} elseif {[string equal $SweepMode "ON"} { # set SweepMode 1 #} elseif {[string match "Without Changing" $SweepMode]} { # set SweepMode 2 #} else { # return -code error "Error in setValue: reading invaild SweepMode value." #} # set mode to "Changing parameters without changing mode - 2 set SweepMode 2 set SStr [expr $newPara / 1000] set SStrHz [expr $newPara % 1000] set SStp [expr [hval $ns/SweepPar/StepFreq] / 1000] set SStpHz [expr [hval $ns/SweepPar/StepFreq] % 1000] set SCyc [hval $ns/SweepPar/SCyc] set data [format %02x%02x%02x%02x%02x%02x $SweepMode $SStr $SStp $SCyc $SStrHz $SStpHz] } "SSteF" { set SweepMode 2 set SStr [expr [hval $ns/SweepPar/StartFreq] / 1000] set SStrHz [expr [hval $ns/SweepPar/StartFreq] % 1000] set SStp [expr $newPara / 1000] set SStpHz [expr $newPara % 1000] set SCyc [hval $ns/SweepPar/SCyc] set data [format %02x%02x%02x%02x%02x%02x $SweepMode $SStr $SStp $SCyc $SStrHz $SStpHz] } "SSCyc" { set SweepMode 2 set SStr [expr [hval $ns/SweepPar/StartFreq] / 1000] set SStrHz [expr [hval $ns/SweepPar/StartFreq] % 1000] set SStp [expr [hval $ns/SweepPar/StepFreq] / 1000] set SStpHz [expr [hval $ns/SweepPar/StepFreq] % 1000] set SCyc $newPara set data [format %02x%02x%02x%02x%02x%02x $SweepMode $SStr $SStp $SCyc $SStrHz $SStpHz] } default { return -code error "in setValue: Wrong setting field." } } set cmd [format %02s%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] sct send "$cmd" } message ]} { return -code error "Error in setValue: $message. While sending command" } return $nextState } ## # @brief Reads the value of a read-node typically following a query command sent to the device # rdValue is the default nextState for getValue() and setValue() # @param idx indicates which control loop or which input channel the command belongs to # @return idle Always returns system state idle - command sequence completed. proc ::scobj::ag1010::rdValue {} { ##################################### # CTRL Codes # CtrlShowLIMITS 2 # CtrlShowPAGC 3 # CtrlShowPMGC 4 # CtrlShowFREQ 5 # CtrlShowSKEY 7 # CtrlShowBurstPar 8 # CtrlShowSweepPar 9 # CtrlShowSVER 13 # CtrlShowMEAS 14 # CtrlShowSTA 15 # # CtrlREJ 42 ##################################### set ns /sics/ag1010 #set ns [sct] if {[ catch { set data [string trim [sct result] " "] hset $ns/responseMsg "$data" #broadcast "rdValue : $data" if {[string first "failed" $data] != -1} { broadcast "Error in LF AG1010 Response: $data" return -code error "$data" } elseif {[string first "read timeout" $data] != -1} { broadcast "Error in LF AG1010 Response: $data" return -code error "$data" } elseif {[string length $data] < 1} { broadcast "Error in LF AG1010 Response: no message returned from device" return -code error "Error in LF AG1010 Response: no message returned from device" } set ctrlCode [format %d 0x[string range $data 4 5]] switch -glob $ctrlCode { 42 { return -code error "Error in rdValue()" } 2 { set FPLH [string range $data 6 7] set FPLL [string range $data 8 9] set RPLH [string range $data 10 11] set RPLL [string range $data 12 13] hset $ns/limits/ForwardPower [format %d [expr 0x$FPLH$FPLL]] hset $ns/limits/ReversePower [format %d [expr 0x$RPLH$RPLL]] } 3 { set AGCPoH [string range $data 6 7] set AGCPoL [string range $data 8 9] hset $ns/AGC/PAGC [format %d [expr 0x$AGCPoH$AGCPoL]] } 4 { set MGCPoH [string range $data 6 7] set MGCPoL [string range $data 8 9] hset $ns/MGC/PMGC [format %d [expr 0x$MGCPoH$MGCPoL]] } 5 { set FreqH [string range $data 6 7] set FreqL [string range $data 8 9] set FreqHzH [string range $data 10 11] set FreqHzL [string range $data 12 13] set Freq [format %d [expr 0x$FreqH$FreqL]] set FreqHz [format %d [expr 0x$FreqHzH$FreqHzL]] hset $ns/FRE/FREQ [expr $Freq * 1000 + $FreqHz] } 7 { set softKey 0x[string range $data 6 7] if {[expr $softKey & 0x80] == 0} { hset $ns/SKEY/SoftOn "Controller takes over the keyboard of controller" } else { hset $ns/SKEY/SoftOn "Host takes over the keyboard of controller" } if {[expr $softKey & 0x08] == 0} { hset $ns/SKEY/Key1 "Off" } else { hset $ns/SKEY/Key1 "On" } if {[expr $softKey & 0x04] == 0} { hset $ns/SKEY/Key0 "Off" } else { hset $ns/SKEY/Key0 "On" } if {[expr $softKey & 0x02] == 0} { hset $ns/SKEY/Key2 "Off" } else { hset $ns/SKEY/Key2 "On" } if {[expr $softKey & 0x01] == 0} { hset $ns/SKEY/Key3 "Off" } else { hset $ns/SKEY/Key3 "On" } } 8 { set SCode [format %02x 0x[string range $data 6 7]] if {$SCode == 0} { hset $ns/BurstPar/BurstMode "Burst Mode OFF" } elseif {$SCode == 1} { hset $ns/BurstPar/BurstMode "Internal Burst Mode ON" } elseif {$SCode == 2} { hset $ns/BurstPar/BurstMode "Change Burst Parameters Without Changing Burst On/Off" } elseif {$SCode == 3} { hset $ns/BurstPar/BurstMode "External Burst Mode ON" } set BRepTH [string range $data 8 9] set BRepTL [string range $data 10 11] hset $ns/BurstPar/BRepTime [format %d [expr 0x$BRepTH$BRepTL]] set BOnTH [string range $data 12 13] set BOnTL [string range $data 14 15] hset $ns/BurstPar/TimeOfPower [format %d [expr 0x$BOnTH$BOnTL]] } 9 { set SCode [format %02x 0x[string range $data 6 7]] if {$SCode == 0} { hset $ns/SweepPar/SweepMode "OFF" } elseif {$SCode == 1} { hset $ns/SweepPar/SweepMode "ON" } elseif {$SCode == 2} { hset $ns/SweepPar/SweepMode "Change Sweep Parameters Without Changing Sweep On/Off" } set SStr [format %d 0x[string range $data 8 9]] set SStrHz [format %d 0x[string range $data 14 15]] hset $ns/SweepPar/StartFreq [expr $SStr * 1000 + $SStrHz] set SStp [format %d 0x[string range $data 10 11]] set SStpHz [format %d 0x[string range $data 16 17]] hset $ns/SweepPar/StepFreq [expr $SStp * 1000 + $SStpHz] set SCyc [format %d 0x[string range $data 12 13]] hset $ns/SweepPar/SCyc $SCyc } 13 { set SNH [string range $data 6 7] set SNL [string range $data 8 9] hset $ns/SVER/SN "$SNH$SNL" set SVerH [string range $data 10 11] set SVerL [string range $data 12 13] hset $ns/SVER/SWVersion "$SVerH$SVerL" set DVerH [string range $data 14 15] set DVerL [string range $data 16 17] hset $ns/SVER/DeviceVersion "$DVerH$DVerL" } 14 { set FPH [string range $data 6 7] set FPL [string range $data 8 9] hset $ns/MEAS/ForwardPower [format %d [expr 0x$FPH$FPL]] set RPH [string range $data 10 11] set RPL [string range $data 12 13] hset $ns/MEAS/ReversePower [format %d [expr 0x$RPH$RPL]] set TPH [string range $data 18 19] set TPL [string range $data 20 21] hset $ns/MEAS/Temperature [format %d [expr 0x$TPH$TPL / 26.4]] } 15 { set MainState [format %d 0x[string range $data 6 7]] switch $MainState { "0" {hset $ns/STA/MainState "Initialization"} "1" {hset $ns/STA/MainState "Controller is in safe loop"} "2" {hset $ns/STA/MainState "Controller is waiting for RFPowerOn Request in LocalMode"} "3" {hset $ns/STA/MainState "Controller is waiting for confirm of RFPowerOn in LocalMode"} "4" {hset $ns/STA/MainState "Controller is in main loop of the LocalMode"} "5" {hset $ns/STA/MainState "Controller is waiting for RFPowerOn Request in RemoteMode"} "6" {hset $ns/STA/MainState "Controller is waiting for confirm of RFPowerOn in RemoteMode"} "7" {hset $ns/STA/MainState "Controller is in main loop of the RemoteMode"} } set state 0x[string range $data 8 9] if {[expr $state & 0x80] != 0} { hset $ns/STA/State/FstRemote "RemoteMode" } else { hset $ns/STA/State/FstRemote "LocalMode" } if {[expr $state & 0x40] != 0} { hset $ns/STA/State/FStExtBurst "External Burst mode ON" } else { hset $ns/STA/State/FStExtBurst "External Burst mode OFF" } if {[expr $state & 0x20] != 0} { hset $ns/STA/State/FStRFError "RFError Detected" } else { hset $ns/STA/State/FStRFError "RFError Not Detected" } if {[expr $state & 0x10] != 0} { hset $ns/STA/State/FStSafetyLP "Error of the Safety Loop Detected" } else { hset $ns/STA/State/FStSafetyLP "Error of the Safety Loop Not Detected" } if {[expr $state & 0x04] != 0} { hset $ns/STA/State/FStExceedRP "Limited of the ReversePower Detected" } else { hset $ns/STA/State/FStExceedRP "Limited of the ReversePower Not Detected" } if {[expr $state & 0x02] != 0} { hset $ns/STA/State/FStExceedFP "Limited of the ForwardPower Detected" } else { hset $ns/STA/State/FStExceedFP "Limited of the ForwardPower Not Detected" } if {[expr $state & 0x01] != 0} { hset $ns/STA/State/FStExceedTmp "Temperature Error Detected" } else { hset $ns/STA/State/FStExceedTmp "Temperature Error Not Detected" } set KeyState 0x[string range $data 10 11] if {[expr $KeyState & 0x80] != 0} { hset $ns/STA/keyState/SoftOn "Host takes over the keyboard of controller" } else { hset $ns/STA/keyState/SoftOn "Controller takes over the keyboard of controller" } if {[expr $KeyState & 0x08] != 0} { hset $ns/STA/keyState/Key1 "On" } else { hset $ns/STA/keyState/Key1 "Off" } if {[expr $KeyState & 0x04] != 0} { hset $ns/STA/keyState/Key0 "On" } else { hset $ns/STA/keyState/Key0 "Off" } if {[expr $KeyState & 0x02] != 0} { hset $ns/STA/keyState/Key2 "On" } else { hset $ns/STA/keyState/Key2 "Off" } if {[expr $KeyState & 0x01] != 0} { hset $ns/STA/keyState/Key3 "On" } else { hset $ns/STA/keyState/Key3 "Off" } } default { return -code error "Unexpected returned values from the device in rdValue()" } } } message ]} { return -code error "Error in rdValue: $message." } return idle } # function names provided # @param scobj_hpath string variabie holding the path to the object's base node in sics (/sample/tc1) # @param sct_controller name of the ag1010 scriptcontext object (typically sct_ag1010) # @param cmdGroup subdirectory (below /sample/tc*/) in which the node is to be created # @param varName name of the actual node typically representing one device command # @param readable set to 1 if the node represents a query command, 0 if it is not # @param writable set to 1 if the node represents a request for a change in settings sent to the device # @param pollEnabled set to 1 if the node property pollable is to be enabled (node gets read every 5 secs) # @param dataType data type of the node, must be one of none, int, float, text # @param unit data units, e.g. m, cm, mm, degree, Hz, W, dW and etc # @param permission defines what user group may read/write to this node (is one of spy, user, manager) # @param rdPara actual device query command to be sent to the device # @param rdFunc nextState Function to be called after the getValue function, typically rdValue() # Praparam wrPara actual device write command to be sent to the device # @param wrFunc Function to be called to send the wrPara to the device, typically setValue() # @param allowedValues allowed values for the node data - does not permit other # @return OK proc createNode {scobj_hpath sct_controller cmdGroup varName readable writable pollEnabled displayable \ dataType unit permission rdPara rdFunc wrPara allowedValues} { # It is a command that is supported by the device if { [catch { set parentnode "ag1010" set ns ::scobj::$parentnode set basepath $scobj_hpath/$parentnode if {2 < [string length $cmdGroup]} { set nodeName "$basepath/$cmdGroup/$varName" } else { set nodeName "$basepath/$varName" } hfactory $nodeName plain $permission $dataType switch $dataType { "none" {hset $nodeName none} "text" {hset $nodeName UNKNOWN} "int" {hset $nodeName 0} "float" {hset $nodeName 0.0} default {hset $nodeName UNKNOWN} } if {$readable == 1} { hsetprop $nodeName read ${ns}::getValue $scobj_hpath $rdFunc $rdPara hsetprop $nodeName $rdFunc ${ns}::$rdFunc if {$pollEnabled == 1} { if {[SplitReply [environment_simulation]]=="false"} { $sct_controller poll $nodeName } } } if {$writable == 1} { hsetprop $nodeName write ${ns}::setValue $scobj_hpath $rdFunc $rdPara $wrPara hsetprop $nodeName $rdFunc ${ns}::$rdFunc if {$pollEnabled == 1} { if {[SplitReply [environment_simulation]]=="false"} { $sct_controller write $nodeName } } } if {1 < [string length $unit]} { hsetprop $nodeName units $unit } if {1 < [string length $allowedValues]} { hsetprop $nodeName values $allowedValues } if {$displayable == 1} { if {2 < [string length $cmdGroup]} { } else { } } } message ]} { return -code error "Error in createNode $message" } return OK } ## # @brief mkAG creates a scriptcontext object for T&C AG1010 Amplifier/generator # #para argList configurable parameters from function call # @return nothing (well, the sct object) proc ::scobj::ag1010::mkAG {argList} { if {[catch { # Generate parameter array from the argument list foreach {k v} $argList { set KEY [string toupper $k] set pa($KEY) $v } MakeSICSObj $pa(NAME) SCT_OBJECT sicslist setatt $pa(NAME) klass environment sicslist setatt $pa(NAME) long_name $pa(NAME) # Create a base node for all the state machines of this sics object #set scobj_hpath /sics/$pa(NAME) set scobj_hpath /sics set ns /sics/$pa(NAME) makesctcontroller sct_$pa(NAME) lfgen $pa(IP):$pa(PORT) ######################################################################################################### # # Create state machines for the following device commands # Note that drivable nodes require the index of the control loop in their call to halt() # Nodes appear in gumtree in the order in which they are created here. # # Initialise the model-dependent list of supported device commands # # cmdGroup subdirectory in which the node is to be created, "P" means under top-parent node # varName name of the actual node typically representing one device command # readable set to 1 if the node represents a query command, 0 if it is not # writable set to 1 if the node represents a request for a change in settings sent to the device # pollEnabled set to 1 if the node property pollable is to be enabled (node gets read every 5 secs) # displayable set to 1 if the node to be displayed on Gumtree GUI, 0 if it is not # dataType data type of the node, must be one of none, int, float, text # unit data units, e.g. m, cm, mm, degree, Hz, W, dW and etc # permission defines what user group may read/write to this node (is one of spy, user, manager) # rdPara parameters LEN and CTRL to be sent to the device # rdFunc nextState Function to be called after the getValue function, typically rdValue() # wrPara actual device field in write command to be sent to the device # allowedValues allowed values for the node data - does not permit other # ########################################################################################################### set deviceCommandToplevel { P limits 1 0 1 1 none {} spy {2 18} {rdValue} {} {} limits ForwardPower 0 0 0 1 int {dW} user {} {} {} {} limits ReversePower 0 0 0 1 int {dW} user {} {} {} {} P AGC 1 0 1 1 none {} user {2 19} {rdValue} {} {} AGC PAGC 0 0 0 1 int {dW} user {} {} {} {} P MGC 1 0 1 1 none {} user {2 20} {rdValue} {} {} MGC PMGC 0 0 0 1 int {dW} user {} {} {} {} P FRE 1 0 1 1 none {} user {2 21} {rdValue} {} {} FRE FREQ 0 0 0 1 int {Hz} user {} {} {} {} P SKEY 1 0 1 1 none {} spy {3 23} {rdValue} {} {} SKEY SoftOn 0 0 0 1 text {} user {} {} {} {} SKEY Key1 0 0 0 1 text {} user {} {} {} {} SKEY Key0 0 0 0 1 text {} user {} {} {} {} SKEY Key2 0 0 0 1 text {} user {} {} {} {} SKEY Key3 0 0 0 1 text {} user {} {} {} {} P BurstPar 1 0 1 1 none {} spy {2 24} {rdValue} {} {} BurstPar BurstMode 0 0 0 1 text {} user {} {} {} {} BurstPar BRepTime 0 0 0 1 int {ms} user {} {} {} {} BurstPar TimeOfPower 0 0 0 1 int {us} user {} {} {} {} P SweepPar 1 0 1 1 none {} spy {2 25} {rdValue} {} {} SweepPar SweepMode 0 0 0 1 text {} user {} {} {} {} SweepPar StartFreq 0 0 0 1 int {Hz} user {} {} {} {} SweepPar StepFreq 0 0 0 1 int {Hz} user {} {} {} {} SweepPar SCyc 0 0 0 1 int {} user {} {} {} {} P SVER 1 0 1 1 none {} spy {2 29} {rdValue} {} {} SVER SN 0 0 0 1 text {} user {} {} {} {} SVER SWVersion 0 0 0 1 text {} user {} {} {} {} SVER DeviceVersion 0 0 0 1 text {} user {} {} {} {} P MEAS 1 0 1 1 none {} spy {2 30} {rdValue} {} {} MEAS ForwardPower 0 0 0 1 int {dW} user {} {} {} {} MEAS ReversePower 0 0 0 1 int {dW} user {} {} {} {} MEAS Temperature 0 0 0 1 int {0C} user {} {} {} {} P STA 1 0 1 1 none {} spy {2 31} {rdValue} {} {} STA MainState 0 0 0 1 text {} user {} {} {} {} STA State 0 0 0 1 int {} user {} {} {} {} STA/State FstRemote 0 0 0 1 text {} user {} {} {} {} STA/State FStExtBurst 0 0 0 1 text {} user {} {} {} {} STA/State FStRFError 0 0 0 1 text {} user {} {} {} {} STA/State FStSafetyLP 0 0 0 1 text {} user {} {} {} {} STA/State FStExceedRP 0 0 0 1 text {} user {} {} {} {} STA/State FStExceedFP 0 0 0 1 text {} user {} {} {} {} STA/State FStExceedTmp 0 0 0 1 text {} user {} {} {} {} STA keyState 0 0 0 1 int {} user {} {} {} {} STA/keyState SoftOn 0 0 0 1 text {} user {} {} {} {} STA/keyState Key1 0 0 0 1 text {} user {} {} {} {} STA/keyState Key0 0 0 0 1 text {} user {} {} {} {} STA/keyState Key2 0 0 0 1 text {} user {} {} {} {} STA/keyState Key3 0 0 0 1 text {} user {} {} {} {} P responseMsg 0 0 0 1 text {} spy {2 42} {} {} {} P SetLimitsFPL 0 1 1 1 int {dW} user {10 2} {rdValue} {FPL} {} P SetLimitsRPL 0 1 1 1 int {dW} user {10 2} {rdValue} {RPL} {} P SetPAGC 0 1 1 1 int {dW} user {4 3} {rdValue} {PAGC} {} P SetPMGC 0 1 1 1 int {dW} user {4 4} {rdValue} {PMGC} {} P SetFREQ 0 1 1 1 int {Hz} user {6 5} {rdValue} {FREQ} {} P SetSoftOn 0 1 1 1 int {} user {3 7} {rdValue} {SoftOn} {1,0} P SetKey1 0 1 1 1 int {} user {3 7} {rdValue} {Key1} {1,0} P SetKey0 0 1 1 1 int {} user {3 7} {rdValue} {Key0} {1,0} P SetKey2 0 1 1 1 int {} user {3 7} {rdValue} {Key2} {1,0} P SetKey3 0 1 1 1 int {} user {3 7} {rdValue} {Key3} {1,0} P SetBurstMode 0 1 1 1 int {} user {7 8} {rdValue} {BurstMode} {0,1,2,3} P SetBRepTime 0 1 1 1 int {ms} user {7 8} {rdValue} {BRepTime} {} P SetBTimeOfPower 0 1 1 1 int {us} user {7 8} {rdValue} {BTofP} {} P SetSweepMode 0 1 1 1 int {} user {13 9} {rdValue} {SweepMode} {0,1,2} P SetSStartFreq 0 1 1 1 int {Hz} user {13 9} {rdValue} {SStrF} {} P SetSStepFreq 0 1 1 1 int {Hz} user {13 9} {rdValue} {SSteF} {} P SetSSCyc 0 1 1 1 int {} user {13 9} {rdValue} {SSCyc} {} } foreach {cmdGroup varName readable writable pollEnabled displayable dataType unit permission rdPara rdFunc wrPara allowedValues} \ $deviceCommandToplevel { createNode $scobj_hpath sct_$pa(NAME) $cmdGroup $varName $readable $writable $pollEnabled $displayable $dataType $unit $permission $rdPara $rdFunc $wrPara $allowedValues } # add HDB structure here ::scobj::set_required_props $ns foreach {hpath klass control data priv type} { /sics/ag1010 environment true true spy part /sics/ag1010/MEAS NXsensor true true user NXsensor /sics/ag1010/FRE NXsample true true user NXsample } { hsetprop $hpath klass $klass hsetprop $hpath privilege $priv hsetprop $hpath type $type hsetprop $hpath control $control hsetprop $hpath data $data } foreach {hpath klass control data nxsave mutable priv alias} { /sics/ag1010/MEAS/ForwardPower NXsensor true true true true user ag1010_MEAS_ForwardPower /sics/ag1010/MEAS/ReversePower NXsensor true true true true user ag1010_MEAS_ReversePower /sics/ag1010/MEAS/Temperature NXsample true true true true user ag1010_MEAS_Temperature /sics/ag1010/FRE/FREQ NXsample true true true true user ag1010_FRE_FREQ } { hsetprop $hpath nxalias $alias hsetprop $hpath klass $klass hsetprop $hpath privilege $priv hsetprop $hpath control $control hsetprop $hpath data $data hsetprop $hpath nxsave $nxsave hsetprop $hpath mutable $mutable hsetprop $hpath sdsinfo ::nexus::scobj::sdsinfo } ::scobj::hinitprops $pa(NAME) } message ]} { return -code error "Error in ::scobj::ag1010::mkAG $message" } } # end of namespace ::scobj::ag1010::mkAG # SICS commands namespace import ::scobj::ag1010::par proc lf_pagc {{para ""} args} { if {$para == ""} { broadcast "[hget /instrument/ag1010/AGC/PAGC] dW" } else { set HEAD 0x96 set LEN 4 set CTRL 3 set CRC 0 set ns /instrument/ag1010 set newPara [string trim $para " "] set data [format %04x $newPara] set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] broadcast "Set Power Level for AGC mode to $newPara dW" sct_ag1010 send "$cmd" } } proc lf_pmgc {{para ""} args} { if {$para == ""} { broadcast "[hget /instrument/ag1010/MGC/PMGC] dW" } else { set HEAD 0x96 set LEN 4 set CTRL 4 set CRC 0 set ns /instrument/ag1010 set newPara [string trim $para " "] set data [format %04x $newPara] set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] broadcast "Set Power Level for MGC mode to $newPara dW" sct_ag1010 send "$cmd" } } proc lf_freq {{para ""} args} { if {$para == ""} { broadcast "[hget /instrument/ag1010/FRE/FREQ] Hz" } else { set HEAD 0x96 set LEN 6 set CTRL 5 set CRC 0 set ns /instrument/ag1010 set newPara [string trim $para " "] if {$para < 0.02 || $para > 2000000} { broadcast "Error: Freqence shall be set between 0.02 Hz and 2 MHz" } else { set Freq [expr $newPara / 1000] set FreqHz [expr $newPara % 1000] set data [format %04x%04x $Freq $FreqHz] set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] broadcast "Set Frequency to $newPara Hz" sct_ag1010 send "$cmd" } } } proc lf_sweep_run {startF stepF scyc {mode 2} args} { if {$mode<0 || $mode>2} { return -code error "Error in setValue: only allowed input values for SweepMode are {0,1,2}" } else { set SweepMode $mode } set HEAD 0x96 set LEN 13 set CTRL 9 set CRC 0 set SStr [expr $startF / 1000] set SStrHz [expr $startF % 1000] set SStp [expr $stepF / 1000] set SStpHz [expr $stepF % 1000] set SCyc $scyc set data [format %02x%02x%02x%02x%02x%02x $SweepMode $SStr $SStp $SCyc $SStrHz $SStpHz] set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] broadcast "Set Starting Frequency at $startF Hz, step at $stepF Hz and $SCyc steps in full sweep cycle under Sweep mode $SweepMode" sct_ag1010 send "$cmd" } proc lf_limits {args} { if {$args == ""} { broadcast "[hget /instrument/ag1010/limits/ForwardPower] dW" broadcast "[hget /instrument/ag1010/limits/ReversePower] dW" } else { set HEAD 0x96 set LEN 10 set CTRL 2 set CRC 0 set ns /instrument/ag1010 foreach {arg val} $args { switch $arg { "FPL" { if {$val > 10040 || $val < 0} { broadcast "Error: The Limit for the Forward Power is 0~10040 dW" } else { set RPL [hval $ns/limits/ReversePower] set data [format %04x%04x%04x%04x $val $RPL 0 0] set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] broadcast "Set Forward Power Limits to $val dW" sct_ag1010 send "$cmd" } } "RPL" { if {$val > 1630 || $val < 0} { broadcast "Error: The Limit for the Reflected Power is 0~1630 dW" } else { set FPL [hval $ns/limits/ForwardPower] set data [format %04x%04x%04x%04x $FPL $val 0 0] set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] broadcast "Set Reverse Power Limits to $val dW" sct_ag1010 send "$cmd" } } default { error "ERROR: $arg should be 'FPL' or 'RPL'" } } } } } proc lf_burst {args} { if {$args == ""} { broadcast "[hget /instrument/ag1010/BurstPar/BurstMode]" broadcast "[hget /instrument/ag1010/BurstPar/BRepTime] ms" broadcast "[hget /instrument/ag1010/BurstPar/TimeOfPower] us" } else { set HEAD 0x96 set LEN 7 set CTRL 8 set CRC 0 set ns /instrument/ag1010 set BurstMode 2 set BRepTime [hval $ns/BurstPar/BRepTime] set TimeOfPower [hval $ns/BurstPar/TimeOfPower] foreach {arg val} $args { switch $arg { "mode" { if {$val<0 || $val>3} { return -code error "Error in setValue: only allowed input values for BurstMode are {0,1,2,3}" } else { set BurstMode $val } if {$BurstMode == 0} { set MODE "Set Burst Mode to OFF" } elseif {$BurstMode == 1} { set MODE "Set Burtst Mode to Internal Mode" } elseif {$BurstMode == 2} { set MODE "Set Burst Mode to Change Burst Parameters without Changing Burst On/Off" } else { set MODE "Set Burst Mode to External Mode" } broadcast "$MODE" } "rtime" { set BRepTime $val broadcast "Set Repetition Period Burst Cycle to $val ms" } "top" { set TimeOfPower $val broadcast "Set Time of Power in Burst Cycle to $val us" } default { error "ERROR: $arg should be 'mode', 'rtime' or 'top'" } } } set data [format %02x%04x%04x $BurstMode $BRepTime $TimeOfPower] set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] sct_ag1010 send "$cmd" } } proc lf_sweep {args} { if {$args == ""} { broadcast "[hget /instrument/ag1010/SweepPar/SweepMode]" broadcast "[hget /instrument/ag1010/SweepPar/StartFreq] Hz" broadcast "[hget /instrument/ag1010/SweepPar/StepFreq] Hz" broadcast "[hget /instrument/ag1010/SweepPar/SCyc]" } else { set HEAD 0x96 set LEN 13 set CTRL 9 set CRC 0 set ns /instrument/ag1010 set SweepMode 2 set SStr [expr [hval $ns/SweepPar/StartFreq] / 1000] set SStrHz [expr [hval $ns/SweepPar/StartFreq] % 1000] set SStp [expr [hval $ns/SweepPar/StepFreq] / 1000] set SStpHz [expr [hval $ns/SweepPar/StepFreq] % 1000] set SCyc [hval $ns/SweepPar/SCyc] foreach {arg val} $args { switch $arg { "mode" { if {$val<0 || $val>2} { return -code error "Error in setValue: only allowed input values for SweepMode are {0,1,2}" } else { set SweepMode $val } if {$SweepMode == 0} { set MODE "Turn Off Sweep Mode" } elseif {$SweepMode == 1} { set MODE "Turn On Sweep Mode" } else { set MODE "Set Sweep Mode to Change Sweep Mode Parameters Without Changing Sweep Mode On/Off" } broadcast "$MODE" } "startF" { set SStr [expr $val / 1000] set SStrHz [expr $val % 1000] broadcast "Set Start Frequency in Sweep Mode to $val Hz" } "stepF" { set SStp [expr $val / 1000] set SStpHz [expr $val % 1000] broadcast "Set Step Frequency in Sweep Mode to $val Hz" } "scyc" { set SCyc $val broadcast "Set Number of Steps in Full Sweep Cycle to $val" } default { error "ERROR: $arg should be 'mode', 'startF', 'stepF' or 'scyc'" } } } set data [format %02x%02x%02x%02x%02x%02x $SweepMode $SStr $SStp $SCyc $SStrHz $SStpHz] set cmd [format %02x%02x%02x%s%02x $HEAD $LEN $CTRL $data $CRC] sct_ag1010 send "$cmd" } } proc lf_meas {} { broadcast "[hget /instrument/ag1010/MEAS/ForwardPower] dW" broadcast "[hget /instrument/ag1010/MEAS/ReversePower] dW" broadcast "[hget /instrument/ag1010/MEAS/Temperature] Degree" } publish lf_limits user publish lf_pagc user publish lf_pmgc user publish lf_freq user publish lf_meas user publish lf_burst user publish lf_sweep_run user publish lf_sweep user # Main process call # @param name short name for the AG1010 Amplifier/Generator # @param IP IP address of the device (e.g. IP of moxabox that hooks up to the AG1010) # @param port port number on the moxabox (typ. 4001, 4002, 4003, or 4004) # @param turning if the parameter is turnable and can be set from the Gumtree # @internal time internal in polling the nodes # IP 137.157.202.219 # Following lines are sued to create the driver #::scobj::ag1010::mkAG { # name "ag1010" # IP 137.157.202.219 # PORT 4001 # tuning 1 # interval 5 #}