12meter control program design
Last Update: 04apr16
The p12mprogram consists of 1 main
programs with 3 cooperating threads:
- p12mMain.c : main program.
- p12mXfThr.c: thread that controls the 12meter (via
ethernet). Does ra,dec -> az,el once a second.
- p12mLogThr.c: does logging of stat info once a second..to
disc and broadcast packets.
- p12mIoThr.c: handles i/o between external user and
p12mProg. Passes requests on to p12mXfThr
p12mMain.c: main program
p12Main program flow is:
- process user options
- data structs: location, precession,nutation structs,
- get lock file to make sure just 1 copy of p12mProg
- connect to p12m telescope controller via ethernet
- initialize the aoQueues used for thread communication,
and io buffer free list
- Start threads:
- start p12mXfThr.c: thread that controls the 12meter,
does 1 sec ra,dec -> az el
- start p12mLogThr.c : logging thread. writes status
info to disk and network once a sec.. also error
- start p12mIoThr.c: thread to handle external user
requests, and then pass the requests to p12mXfThr
- currently there can be a maximum of 5 io threads
active at one time.
- Enter main loop:
- wait (with timeout) for external user connect request:
- If signal present, goto cleanup ,exit
- the signal handler catches: SIGHUP,SIGINT,SIGTERM
- If connect request, start p12mIoThr for this
request. log in active ioThr table
- If timeout (no connect request) check if any
ioThreads have exited.. if so, do resource cleanup.
- free up resources, clear lock file, exit.
A number of routines common to the other
threads are located in p12mProg.c
- sleepSecs: wait routine
- msgThrToThr, putNodeQ, getNodeQ: thread to thread
- For interthread communication aoQueues are used.
- p12mXfThr and p12mLogThr both have input queues based
- the queue is a linked list of nodes with a semaphore
- timeDifSec: compute time differences between 2 times
- dbgOut: output debugging info
- messageLxxxx : send warning, error messages from threads
- Linux time (secs from 1970) is used to track many times.
- This get around the wrapping at midnite or years.
- The program was originally written to use the 12meter
track array option..
- you send time stamped az,el positions ahead of time to
- It uses the previous and next points to compute a
velocity. This caused large accelerations, de
accelerations at the end of a cross strip (more
- The IoThr occasionally wants status info that is stored in
the xfThr status blocks during the 1 sec tick processing (to
send back to the requester).
- Rather than go through the cmdQueue for request, reply..
ioThr can access info in the XfThr struct in a read only
- pxfI->tickI.secMidBusy is a
- It is set to minus the current time when
xfThr starts to modify it's status block,
- It is set to plus the current time xfThr is done
- IoThr checks this flag. If negative, it will wait a few
millisecs and try again. This repeats till it gets the
data or times out.
p12mXfThr.c: radec->az,el and 12m
xfThr is the thread that controls the 12meter
telescope via ethernet. Once a second it computes ra,dec to az,el
and then sends the info to the 12meter. It takes it's input
from an aoQueue. Once a second status info is sent to the logging
xfThr program flow is:
Further explanation of some routines:
- started by p12mMain.
- xfInitialState(): make sure the telescope is in a known
state on startup:
- see if this is the first time through, or a reconnect to
- If 1st time. make sure telescope is at least in stop mode.
- initialize some counters
- if not the first time, then reread the status info from
- set the following state in the 12meter
- turn off set point offsets
- turn off tracking offset mode
- set coordinate mode to horizon (we send az,el not ra,dec)
- Turn off model corrections (we compute model offsets
- load 0's into 12meter model correction params (just in
- Force dut1 correction to be 0.. (we do the dut1 correction
in pntmXfThr, and the send utc times to controller.
- on successful exit, set flag saying that we completed
- Loop forever (or until signal)
- If we got a signal, exit loop..return from p12mXfThr
- xfTickChk() - see if we should wait for the arrival
of 1 sec tick.
- xfSecsTillNextWait().. return true if we are within
.1 secs of the next tick (define:(SEC_BEFORE_TICK_TO_WAIT)
- if need to sleep: sleeptilltm() wakeup at next
- xfCmpTimes(): load XF_TIME struct with time info
for this sec: ast,utc,jd,last..etc
- return xfTickChk() true..
- If xtTickChk() returned true
- Compute seconds till next tick
- If close to next tick, go back to top of loop.
- wait for commands on input queue
- getNodeQ(): use timeout that will wake us at .9
secs of this second
- If we got a command on input queue, process it:
- If command requires a reply, build the reply packet and
- end xfThr infinite loop
xfTickProc: processing at
start of each tick:
- statWd.trValidPnt is set to 0 when p12mProg initializes
- If we have a pending coordinate point
- user request tracking points via the command pnt tr c1 c2 -t
- these are sent to ioThr and then to xfThr via it's input
- see if the point becomes active on this sec. If so copy it
to the current tracking point struct.
- coord points can have a timestamp when they should
activate. If no timestamp, they become active when received.
- Set statWd.trValidPnt to true.
- This keeps us from tracking a position before we have
received any requests.
- There is only 1 pending point. If the user sends a 2nd point
before the 1st is activated, the 1st is discarded and the 2nd
point becomes the pending point (you can't queue more than 1
- If statWd.trValidPnt is true: we've received at least
1 tracking request, and it has been activated.
- We convert the coord request to az, el
- we do this twice: once for this 2nd and once for the next
- we need a velocity for ramp mode.
- xfCmpTimes(): compute times for the timestamp
sent in. Load xf_time struct
- jd, asttime, utc time, dut1frac, lmst,last (local
mean/apparent siderial time)
- xfConvert(): converts astronomical
pos,times,offsets, rates to az,el, timestamp
- xfDoOffsets(): add on model and any great circle
offsets (pnt dbg gc azOff elOff).
- Keep track of cumulative offsets (if -r rate was included)
- Compute the az,el velocities for the 1 second step (needed
for ramp mode)
- store the requested az,el,tm,in the azelBuf. This holds
the requested points. Will be used later to compute the
- p12mdTrLdRamp(): load ramp data into controller.
- The ramp will take affect when it is received, so we don't
want to be too far after the tick..
- If we are a little late (millisec) it will just use be
using the velocity from the previous sec.. So the error in
the acceleration over 1 sec.
- Note that we do this conversion as long as we have an active
tracking point.. whether or not we are in tracking mode.
- xfReadP12mStat(): Read the status blocks from the 12m
controller using group read.
- The status will be time stamped by the 12m controller for
when the data was grabbed (4ms cycle).
- Typically this take 20 ms for the read.
- Compute the current telescope state from the status block
(off, standby, stop,track mode).
- Below here is the non time critical portion of the 1sec
- if statWd.trValidPnt is true (we have a valid tracking
- back convert ra,dec J2000 from the az,el read back from the
- Compute the tracking error:
- Interpolate the requested position to the timestamp of the
data read back by xfReadP12mStat()
- We store a history of the requested positions i azelBuf.
this is searched to get the current req.
- This was needed for trackArray mode. Ramp mode probably
doesn't need azelBuf...
- We store the last used in pxfI-azelLast
- See if we are in the process of changing states:
- statWd.stChangeReq keeps track of state
- This routine sometimes needs to change state (stop telescope
when re initializing..etc).
- This can take many seconds for the controller to change
state (stop telescope,etc). stChangeReq keeps track of this.
- When changing states, you need to transition to the next
- eg: moving, not moving, breaks on, power of...
- Send info for this second to the logThr
- return from xfTickProc()
xfProcCmd: Process a command request
p12mLogThr.c: logging thread
p12mIoThr.c: handle I/O for external
<- page up