9/2
Processing a command from bicepViewer through bicepControl
SPT code: first look
9/3
Description of MCE Code from Walt Ogburn
Talk to Ken Aird
9/4 - 9/5
9/6-9/16
9/17 - 9/18
9/19
9/24
MAS code organization
9/25
9/26
9/29
Talk with Ken: SPT code
SPT code: MuxReadoutSoftware
DIOServer.pdf
HardwareManagerServer.pdf

9/2

Processing a command from bicepViewer through bicepControl

bV = bicepViewer
bC = bicepControl
bM = bicepMediator

bV: type command into gui: "lockin ac"
service_TclControl(): cmd=send
  tc_send(): cmd=lockin ac
    //pack message to be sent:
    obj_to_net: id=input, ntype=256
    //send message to bicepControl
    nss_send_msg(): state=DONE

Message sent to bicepControl:

bC:
in while loop:
  //read incoming message from bV
  chan io_fn(sock_read_fn)
    nrs_read_msg(): called in a switch()
      return NET_READ_DONE
    call sock->rcvd_fn(cc_sock_rcvd_fn): id=input
      //extract msg from network buffer
      net_start_get()
      net_to_obj(): data=lockin ac //read network buffer into a useable object
      net_end_get():
      //forward contents of message to appropriate thread:
      pack_scheduler_command()
      msg.packSerializedData()
      add_scheduler_channel(): calls add_writable_channel to send scheduler command

  //write command to control pipe (piped to bC)
  chan io_fn(pipe_write_fn)
    pipe->write() => case PIPE_OK
    call PIPE_SENT_FN(sent_Scheduler)
      rem_scheduler_channel() //watch client threads for readability
        add_readable_channel()
        add_readable_channel()

  //read control command from bC pipe
  chan io_fn(pipe_read_fn)
    pipe->read() => PIPE_OK
    call PIPE_RCVD_FN(cc_pipe_rcvd_fn): id=log //act on the receipt of a message to be forwarded to a client
    //pack message to be written to the client socket
    net_start_put()
    obj_to_net(): id=log
    net_end_put()
    add_writable_channel() //put in queue to be sent to socket

  //write log command to bV
  chan io_fn(sock_write_fn)
    nss_send_msg(): return NET_SEND_DATA
    call SOCK_SENT_FN(cc_sock_sent_fn)
      add_readable_channel() //allow receipt of another message from the client reply pipe.

Message sent to bV:

tc_server_event()
  nrs_read_msg(): case NET_READ_DONE
  net_to_obj()

Back in bC, continue forwarding command to bM:

  //read pipe with original command "lockin ac"
  chan io_fn(pipe_read_fn)
  pipe->read() => PIPE_OK
  call PIPE_RCVD_FN(rtc_pipe_rcvd_fn)
    obj_to_net(): id=datasystem //pack message to be sent to bM
    add_writable_channel()

  //write message to bM channel
  chan io_fn(sock_write_fn)
    nss_send_msg(): return NET_SEND_DATA
    call SOCK_SENT_FN(rtc_sent_fn)
    add_readable_channel() //listen for response from bM

Message received by bM:

//bM sits in the while loop inside of serviceMsgQ(), waiting for messages from above or below.
in while loop: (Control.cc: serviceMsgQ() )
  call netCommHandler_.readNetCmd()
    call netCmdHandler_.read()
      nrs_read_msg() => NET_READ_DONE     //read message
      net_to_obj()                        //parse message
      NET_READ_HANDLER(readNetCmdHandler) //forward message
        forwarder_->forwardNetCmd()
        calls antennaControl_->SendTaskMsg()

SPT code: first look

Looking at:
  /home/sptdaq/gcpDeployMatlab/gcp
new directory:
  /gcp/receiver
  /gcp/muxutil -> hardware stuff
in mediator/spt/, many new files:
  Deicing, DioMsg, FridgeConsumer, Heater, Holo, PointingTelConsumer, PTel,
  Receiver, SecondaryConsumer, SptWx, TipperSshClient


We may need the following:
MceConsumer.cc, MceConsumer.h, MceConsumer.o
MceControl.cc, MceControl.h, MceControl.o
MceManagerClient.cc, MceManagerClient.h, MceManagerClient.o
MceNetCmdForwarder.cc, MceNetCmdForwarder.h, MceNetCmdForwarder.o
MceControlMsg.h
MceData.h

Look at PTel and PointingTelComsumer.

For Tomorrow:
  - Continue looking through spt code for Scanner.cc, SignalTask.cc
  - Try to write out MceConsumer, MceControl classes.
  - Look for Ken.

9/3

For Today:
  - Continue looking at spt code
  - Check out and compile MCE code

Description of MCE Code from Walt Ogburn

An email from Walt describing the MCE code:
1) MCE code

My code for reading MCE data into C is in CVS on bicep0.caltech.edu.  I'm also
attaching a tarball, which is probably more convenient for you.

(The CVS repository is at /home/cvsroot.  With the bicep password, you can
access it with
export CVSROOT="bicep@bicep0.caltech.edu:/home/cvsroot"
cvs checkout ... etc.)

The basic function of this code is to read the raw data file and the runfile
into a structure in memory.  My code can write out dirfile format, which
should presumably be similar to the structure needed to get the data into
GCP, since they both use a fixed register map (which can be loaded at runtime
or compiled in).

Organization of my code:
* masutils/datafile : reads the MCE raw data files
* masutils/runfile : reads the auxiliary MCE runfiles
* masutils/regmap : handles register maps (which can be compiled in or loaded
at run time)
* masutils/mas2dir.c : convert MCE data to dirfile format
* masutils/rmap2h.c : convert a register map in text file format to a C header
file
* masutils/bicep2_regmap.txt : the register map in text-file format (for
loading at runtime)
* masutils/bicep2_regmap.h : the register map as a C header file (to be
compiled in)

To compile mas2dir, you'll also need the dirfile library by Ted Kisner:
http://cmb.phys.cwru.edu/kisner/code/dirfile/

It should be possible for you to use mas2dir as a starting point.  Or, if you
will define the socket layer and work on the GCP end, I can adapt my code as
needed.

2) Socket layer

So far, there's no socket layer.  Erik Leitch was planning to write this, but
I don't now if & when he will have time to work on it.  Are you willing to
write one?

In MAS (MCE Acquisition System), the data is written out in frames, where each
frame includes a single reading for each pixel.  In GCP, on the other hand,
the frame rate is slower, so that one GCP "frame" may contain the data from
100 or so MCE "frames."

Presumably there will be a process that runs on the MCE machine, waiting until
enough MCE frames have been collected to make one GCP frame.  It will then
read the runfile and data file, assemble them into registers according to the
register map, and send the structure across the network to the GCP machine.
My code reads the files into registers and handles the register maps.  I'm
not sure what form the network protocol should take (it will probably depend
on what's most natural for GCP).

3) Dummy MCE output

What form would be most convenient for reading into GCP?  I am posting a few
example raw data files here:
http://www.ugcs.caltech.edu/~reuben/dump/mce_examples.tgz

You can use the code to load them into a memory structure or to generate a
dirfile.

Talk to Ken Aird

SPT Wiki

Three ideas for eating data from the MCE:
1) Pack up code in the MAS and send over UDP to Antenna Control. In this way, we could then use the existing antenna control code, such as NetDataParse.cc to turn this into archive records.
Here the MCE simply sends data over the UDP whenever it wants to.
Ken has code for UDP -> XML. I can ask him for it if we want it.

2) Use Ken's XML mechanisms for a TCP/IP. In this way, MAS would pack the data into xml format and send it to an XMLConsumer. Then a new class MceDataFrameManager would provide functions for unpacking the xml and packing it into a register record.
In this mechanism, the gcp must poll the MCE every 1 second, asking for data.

3) Send raw bolometer data over a TCP/IP. This is more efficient for single data types. Questions: How does the current bicep interface to bolometer data, i.e. what modules of gcp are used for this interface? This is probably not the easiest to impliment.

Scripting:
control/code/unix/libunix_src/
    bicep/specificregs -> define everything in archive record
control/code/unix/control_src/
    bicep/specificscript.c -> add_specific_script_commands(): add commands here.

Debugging / Dummy output:
How does the MCE interface to hardware?
Is there a way of producing a stream of predictable dummy output that I can pipe into my control software for testing? Can then check that the gcp produces the same data as the input (dummy mce).

From Ken's notes:

How to add support for a new hardware device to the Control Program (XML mechanism)

    * Add archive/monitor register definitions to control/code/unix/libunix_src/specific/specificregs.c
    * Add XML Consumer
          o Add util/specific/XXXDataFrameManager.cc and .h based on PointingTelDataFrameManager
          o In mediator/Scanner.cc add:
                + #include "gcp/util/specific/XXXDataFrameManager.h"
                + XXXConsumer = 0; // in constructor
                + threads_.push_back(new Thread(&startXXXConsumer, &cleanXXXConsumer, 0 "XXXConsumer"));
                + In pollConsumers()
                      # if(XXXConsumer_) { XXXConsumer_->sendDispatchDataFrameMsg(); }
                + THREAD_START(Scanner::startXXXConsumer)...
                + THREAD_CLEAN(Scanner::cleanXXXConsumer)...
          o In mediator/Scanner.h
                + static THREAD_START(startXXXConsumer);
                + static THREAD_CLEAN(cleanXXXConsumer);
                + XMLConsumer* XXXConsumer_;

9/4 - 9/5

At Caltech Bicep collaboration meeting

9/6-9/16

Study for the Candidacy Exam

9/17 - 9/18

Take Candidacy Exam

9/19

Back at Work!!

What to do next:
  1) Look at mas code on bicep0
  2) Figure out what data format the raw data comes out in, and what I could write across a network connection in.
  3) Talk to Ken again.

Unpack and copy mas code to my home directory: ~/mce/

MAS code:
three directories:
  mas ->
  mas_trunk ->
  mce_script ->

9/24

Orientation stuff is going on.

My email:
1) What data formats should we use?
Ans: look at mce code and figure out how it stores data. Then talk to Ken again.
2) Archiving:
Ans: archiving will take place on the GCP side. We will need to match up serial numbers from the Antenna Layer and the MCE to make complete registers. This is something that will eventually have to be taken care of, but is not my first concern.
3) Dummy Code output from the mce.
Ans: There exists a dummy driver code. I need to figure out exactly what I want then talk to the UBC guys and/or Walt.

Walt's Email:
Thoughts on Socket Layer:
MAS: data is written out in frames, where 1 frame > 1 reading of each pixel.

> **GCP**: 1 frame > ~100 readings for each pixel.

Walt's thoughts: Mas waits until enough MCE frames are collected to make one GCP frame. Then make data struct from the data file, run file, and register map. Send this completed register to the GCP.
It actually might be easier to just send over the frames as they come out and deal with them on the GCP side.

Where to go from here:
1) Look at MAS code and figure out what type of data it reads out in. Probably some sort of binary.
2) Talk to Ken Aird about how the SPT sends the bolometer data across the connection.
3) Write an interface similar to the SPT interface into the GCP.
4) Write a mock program that outputs a time-syncrhonous stream of data to feed into the GCP.
5) Make them work together.

MAS code organization

Three sub-directories: mas, mas_trunk, mce_script

mas:
mas has subdirectories:
  - applications
  - config
  - driver
  - include
  - interfaces

Can't find the masutils directories that appear to hold the code I need to look at. Emailed Walt about this.

9/25

masutils is actually not in the mce code, which was written by UBC. Masutils is an additional collection of code that Walt wrote himself.

Look into masutils:
masutils/datafile : reads the raw mce datafiles.
read_dataframes() -> read data into uint32_t \* buf

I think read_dataframes() has what I need to know:
Data is read out of the datafile with the commands:

    uint32_t count = (last_frame - first_frame + 1) * m->frame_len;
    if (fread (buf, sizeof (uint32_t), count, m->f) < count)
        return 1;

For reading the runfile, need parse_runfile_data() in runfile.c:
This calls one of 3 methods: parse_uint8, parse_uint32, parse_double

9/26

In mas2dir.c:

read_runfile_regs(char* runfname, flat_regs * &regs, regmap* rmap);
...
open_datafile(datafname, data_mode, &datafile);
...
uint32_t * data;
read_dataframes(&datafile, 1, datafile.nframes, data)  // fills data[]

where
int read_dataframes (mas_datafile * m, int first_frame, int last_frame, uint32_t * buf);

Thus data[] is now an array of bites that correspond to the bolometer readings.

9/29

load_data.c

int read_dataframes (mas_datafile * m, int first_frame, int last_frame, uint32_t * buf)
{
    uint32_t count;
    int res;

    count = (first_frame - 1) * m->frame_len;
    res = fseek (m->f, count * sizeof (uint32_t), SEEK_SET);
    if (res != 0)
        return 1;

    count = (last_frame - first_frame + 1) * m->frame_len;
    if (fread (buf, sizeof (uint32_t), count, m->f) < count)
        return 1;

    return 0;
}

runfile.c

int parse_runfile_data (flat_regs * reg, regmap_entry * re, const char * s)
{
    char * buf = ((char *)reg) + re->offset;

    TRACE("    dt=%d, len=%lu, ofs=%lu.\n", re->data_type, re->samples_per_frame, re->offset);
    switch (re->data_type)
    {
        case _DATA_UINT8 : return parse_uint8 (s, (uint8_t *)buf, re->samples_per_frame)
        case _DATA_UINT32 : return parse_uint32 (s, (uint32_t *)buf, re->samples_per_frame);
         case _DATA_DOUBLE : return parse_double (s, (double *)buf, re->samples_per_frame);
     }
     printf ("Don't know how to parse runfile entries of data type %d.\n", re->data_type);
    return 1;
}

int read_runfile_line (const char * ll, uint32_t * section, regmap * rmap, flat_regs * reg)
int read_runfile_regs (const char * fname, flat_regs ** reg, regmap * rmap)
{
    FILE * f;
    uint32_t section;
    char buf[MAX_LINE_LENGTH];
    int res;

    f = fopen (fname, "rt");
    init_flat_regs (reg, rmap);
    section = 0;

    while (!feof (f))
    {
        fgets (buf, MAX_LINE_LENGTH, f);
        res = read_runfile_line (buf, &section, rmap, *reg);
    }
    fclose (f);
    return 0;
}

Talk with Ken: SPT code

Questions:
  - In the runfile, what do the codes mean, i.e. < RB cc ... -> Done
  - What are the serial numbers that allow us to synch the data files with the antenna layer information?
  - How does the MAS know when to stop writing and close a data file?
  - How does the MCE get a time signal? -> Done
  - How does the gcp synch the antenna and MCE information? -> Done With the sync box timestamp.
  - What hardware and OS is MAS run on? -> Done
  - Where is PutData() defined? It is used in mas2dir.c
  - Who at UBC can answer my questions about the MCE?
  - What is the archive format? Dirfiles? Something else? I assume the code to do this already exists in gcp?

Need:
  - Collate data frames fom the mce with the antenna layer
    ~ match serial numbers that tag each frame in mce and antenna
    ~ there is a PCI card in the machine running the gcp that generates an interrupt when the mount encoder values are supposed to be read
    ~ uses a SyncClock32 card.
  - Archive register definitions
  - Mapping from MAS to archive register (if different)
  - define interface over net between MAST (MAS Transfer)
    ~ Can we re-use the bolometer-data interface from the spt (DIOserver, HardwareManagerServer)?
    ~ What about house-keeping registers?
      - Tack onto bolometer data somehow
      - Use xml consumer
      - something new

SPT code: MuxReadoutSoftware

The Berkeley MuxReadoutSoftware is a hardware-software interface that talks to the gcp for the spt. There are two server managers:
DIOserver
  Command connection and separate data stream connection
HardwareManagerServer
  Command - response connection that uses xml
  There exists a simplified version of this.

Thus the gcp in spt has code that talks to the DIOserver and the HardwareManagerServer. If I can get a layer of software on the MAS side that is similar to these two, then I can virtually copy the spt gcp code into the bicep gcp code.

To Do:
  - Read DIOserver.pdf
  - Read HardwareManagerServer.pdf
  - Email Walt about some of the questions
  - Email Eric Leitch about using the existing DIOserver and HardwareManagerServer code, at least as a starting point.

DIOServer.pdf

Data is transfered to the data acquisition PC via a parallel bus. This parallel bus is read out by a fast Digital IO (DIO) board. The bitstream also contains: timestamps, board addressing info, redundancy checks.
The DIO timestream can be used for:
  - Collection of science data
  - Bolometer and SQUID diagnostic/tuning algorithms
  - Real-time monitoring applications.
Data is distributed via TCP. The DIO board is controlled by a TCP server. A client can then request data from selected channels, or the entire DIO bitstream in raw format.
HardwareManager separately controls the setup and tuning of readout electronics while keeping track of configuration parameters.

Data Access Sessions
The client tells the server what data, how many samples, and when to stop.
Uses XML fragments as a the basis of the command-language.
There are 2 sockets: Command Socket and Data Socket.
Command Socket: sends XML commands. Server repoies with a format string.
Data Socket: sends binary data.

HardwareManagerServer.pdf

Purpose:
  - Manage an instillation of the readout hardware.
  - Provide a way for users to interact with the hardware.
Control commands are sent through a serial RS485 port using ascii Modubs protocol.
All commands pass through MUX::HardwareManager. Mediates communication and error handling between hardware and software.
Fast bolometer data from the readout boards is sent through the DIOServer.

Interface to the Readout
Commands (configuration, setup, control) are sent to the MUX::HardwareManager with XML commands over TCP/IP.
The MUX::HardwareManager listens to a TCP port for connection requests (from gcp), and responds to thtem.


Questions:
  1) How do I use a debugger (ex. gdb)?
  2) What is a "Consumer," as in AntennalConsumer ?