• Email Diogo Alves for meeting discussing technical implementation [priority:: medium] [due:: 2024-10-14] [completion:: 2024-10-14]

Meeting with Diogo

We need to implement corrections on

  • FESA class on machine with a timing card
    • Settings
      • xs (time)
      • ys (correction )
      • enable/disable
      • zero-property to reset field
    • Send UDP packets after C-start, every N ms (20 ms for SPS MBI)
    • Header for UDP available on NFS, basic implementation for constructing the UDP packet see below
  • When the packet is sent to gateway, we need to know which magnet to send packet to (basically ID), set active_mask with correct index and set to channels
  • Test FESA class by pointing it to your own server and make sure UDP packets arrive in time.
sender : sender.cpp
	g++ -Wall $^ -o $@ -I/user/pclhc/include/fgc/ -I/user/pclhc/include/fgc/classes
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <netdb.h>
#include <strings.h>
 
#include <string>
#include <byteswap.h>
#include <sys/time.h>
#include <fgc_rtdata.h>
 
class UDPSender
{
private:
    int iSock;
    struct hostent *ptHent;
    struct sockaddr_in ptDestination;
 
public:
    UDPSender(std::string sUDPHost, int iUDPPort)
    {
        iSock = ::socket(AF_INET, SOCK_DGRAM, 0);
        ptHent = ::gethostbyname(sUDPHost.c_str());
	if (ptHent == NULL) {
	    fprintf(stderr, "gethostbyname() failed\n");
	    exit(-1);
	}
        uint32_t ui32AddrTmp;
        ptDestination.sin_family = ptHent->h_addrtype;
        ::bcopy(ptHent->h_addr, (char *)(&ui32AddrTmp), ptHent->h_length);
        ptDestination.sin_addr.s_addr = ui32AddrTmp;
        ptDestination.sin_port = ::htons(iUDPPort);
    }
    int send(struct fgc_udp_rt_data *ptPacket)
    {
        return ::sendto(iSock, ptPacket, sizeof(*ptPacket), 0, reinterpret_cast<struct sockaddr*>(&ptDestination),
                sizeof(ptDestination));
    }
    ~UDPSender()
    {e
        ::close(iSock);
    }
};
 
 
int main() {
 
    struct fgc_udp_rt_data tMyPacket;
 
    std::string udpHost = "gatewayName";
    uint32_t udpPort = 1905;
    
    UDPSender *udptx = new UDPSender(udpHost, udpPort);
 
    struct timeval ts;
    for (uint32_t i = 0; i < 10; ++i) {
	// tMyPacket.header.id = ; // Please check with someone from EPC
 
	gettimeofday(&ts, NULL);
	tMyPacket.header.send_time_sec = htonl(ts.tv_sec);
	tMyPacket.header.send_time_usec = htonl(ts.tv_usec);
	
	// tMyPacket.apply_time_sec = htonl(); // Please check with someone from EPC
	// tMyPacket.apply_time_usec = htonl(); // Please check with someone from EPC
 
        tMyPacket.header.sequence = htonl(i);
 
	uint64_t channelMask = 0x1;
	tMyPacket.active_channels = bswap_64(*((uint64_t *)(&channelMask)));
	
	bzero(tMyPacket.channels, FGC_MAX_RTDEVS_PER_GW * sizeof(float));
	float dI = 1e-3;
	tMyPacket.channels[0] = htonl(*((uint32_t *)(&dI)));
	
	udptx->send(&tMyPacket);
 
	usleep(1000000);
    }
 
    delete udptx;
    
    return 0;
}
 

Proposed design

Drawing 2024-11-11 18.01.17.excalidraw

⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠ You can decompress Drawing data with the command palette: ‘Decompress current Excalidraw file’. For more info check in plugin settings under ‘Saving’

Excalidraw Data

Text Elements

FGC.RTC.MBI

FESA

MBI

FGC

CTR

SCY / ms

FEC

Field predictions

B Correction (value)

I Correction (value)

MR / calibration fn B2I

SPSBEAM/B

LSA

drive dI (discrete function)

dB

dI scalar over UDP

MBI

SPSBEAM/BHYS (correction)

SPSBEAM/B

MBI/IREF

FGC

MR calibration fn B2I

LSA

drive

MR copy

Link to original

Matthias will implement the FESA class.

  • Follow up on implementation of FGC real-time channel correction FESA class [due:: 2025-02-01] [priority:: high] [start:: 2025-02-01] [completion:: 2025-03-13]
  • Test FGC real-time channel correction FESA class during SPS Beam Commissioning 2025. [due:: 2025-03-01] [priority:: high] [start:: 2025-03-10] [completion:: 2025-09-01]

Critical considerations

For the design of the FESA class we also have to take into account feasible steps between each regulation step, i.e. every 20 ms, as highlighted by Quentin. While it is technically possible to interpolate the and prepone the trimmed to play in reality smaller steps, this needs to be taken into consideration. Steps in the magnitude of would result in ripples in the measured current that are unwanted.

Prototype

Matthias developed a FESA class: