/* Alibava control via USB FT245R or raw Ethernet interface */ /* Copyright I.Tsurin Liverpool University V1.0 (30.09.2011) */ /* */ /* http://twiki.ific.uv.es/twiki/bin/view/Atlas/ALiBaVa */ /* Acknowledgment: Paulo Pedreiras, Out.2005 RCAI 05/06 */ /* http://www.ieeta.pt/~pedreiras/resources/rcai/raw-sr.c */ /* Includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include // the L2 protocols #include #define ETH_SAFE_LEN (ETH_DATA_LEN - 100) #define DEVICE "eth0" int s = 0; // Socket descriptor unsigned char *eth_head; // byte pointer to ethenet header unsigned char *eth_data; // byte pointer to ethernet data field struct ethhdr *eh; // structured pointer to ethernet header struct sockaddr_ll socket_address; void *buffer = NULL; /* Local host NIC MAC address */ unsigned char src_mac[6] = {0x00, 0x1D, 0x09, 0xB1, 0x46, 0x6F}; /* Front end address template */ unsigned char dest_mac[6] = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00}; void sigint(int signum); int eth_raw_init(); unsigned char l=1; unsigned char O=0; unsigned ePackID; unsigned eCommID; #define Nt 26 unsigned char Temp[Nt]; FILE *fp; /* Commands */ #define iniNOP 0x00 #define iniCTR 0x01 #define iniDAC 0x02 #define iniASIC 0x03 #define iniDEL 0x04 #define iniLAT 0x05 #define iniRPL 0x07 #define getEVT 0x08 /* Board control */ #define RPlength 652 #define MCA 0 #define LU 2 #define MC l #define MB O #define Reset 0 #define Write 1 #define Read 2 #define iCLK l #define eCLK O #define iTRG l #define eTRG O #define iRES l #define eRES O #define cENA l #define cDIS O #define CRoctet(CLK, TRG, RES, CAL) \ ((CAL & 0x01)<<3 | (RES & 0x01)<<2 | (TRG & 0x01)<<1 | (CLK & 0x01)) /* DAC controls */ #define SDI0 O #define SDI1 l #define CLK0 O #define CLK1 l #define nCS0 O #define nCS1 l #define nLD0 O #define nLD1 l #define nRS0 O #define nRS1 l #define Tcode(Tvalue) (int)(4095.*(Tvalue + 5.- 2.048)/5.) #define DACoctet(nRS, nLD, nCS, CLK, Dbit) \ ((nRS & 0x01)<<4 | (nLD & 0x01)<<3 | (nCS & 0x01)<<2 | (CLK & 0x01)<<1 | (Dbit & 0x01)) /* Beetle controls */ #define SCL0 O #define SCL1 l #define SDA0 O #define SDA1 l #define RW0 O #define RW1 l #define ASICoctet(MemA, RW, SCL, Dbit) \ ((MemA & 0x1F)<<3 | (RW & 0x01)<<2 | (SCL & 0x01)<<1 | (Dbit & 0x01)) /* Delay controls */ #define SI0 O #define SI1 l #define SC0 O #define SC1 l #define AE0 O #define AE1 l #define DELoctet(AE, SC, Dbit) \ ((AE & 0x01)<<2 | (SC & 0x01)<<1 | (Dbit & 0x01)) unsigned MBset[] = { /* control register */ 0x30, /* threshold DACs 863 */ 0x863, 0x863, 0xFFF, 0x827, /* ASIC 0 settings: 1st octet is I2C geoAddress */ 0x20, 20, 0, 0x00, 1, 0x4C, 2, 0x0A, 3, 0x0A, 4, 0x00, 5, 0x00, 6, 0x05, 7, 0x00, 8, 0x00, 9, 0x00, 10, 0x0D, 11, 0x82, 12, 0x69, 13, 0x14, 14, 0x1A, 15, 0x66, 16, 0x10, 17, 0x1A, 18, 0x00, 19, 0x09, /* ASIC 1 settings: 1st octet is I2C geoAdress */ 0x21, 20, 0, 0x00, 1, 0x4C, 2, 0x0A, 3, 0x0A, 4, 0x00, 5, 0x00, 6, 0x05, 7, 0x00, 8, 0x00, 9, 0x00, 10, 0x0D, 11, 0x82, 12, 0x69, 13, 0x14, 14, 0x1A, 15, 0x66, 16, 0x10, 17, 0x1A, 18, 0x00, 19, 0x09, /* external delay line */ 0x00, /* ASIC trigger latency */ 15, /* data paket length */ 652 }; /***************************************/ /* Moterboard controls */ /***************************************/ int NOP(void) { *(eth_data++) = 2; // packet length *(eth_data++) = iniNOP; // define command return 2; } int CTRset(unsigned Dbyte) { *(eth_data++) = 3; // packet length *(eth_data++) = iniCTR; // define command *(eth_data++) = (unsigned char)(Dbyte&0xFF); //CRoctet(iCLK, iTRG, iRES, cDIS); return 3; } int LATset(unsigned Dbyte) { *(eth_data++) = 3; // packet length *(eth_data++) = iniLAT; // define command *(eth_data++) = (unsigned char)(Dbyte&0xFF); return 3; } int RPLset(unsigned Dbyte) { *(eth_data++) = 4; // packet length *(eth_data++) = iniRPL; // define command *(eth_data++) = (unsigned char)((Dbyte>>8)&0xFF); *(eth_data++) = (unsigned char)((Dbyte>>0)&0xFF); return 4; } int RUNgo(void) { *(eth_data++) = 2; // packet length *(eth_data++) = getEVT; // define command return 2; } /***************************************/ /* Threshold DACs */ /***************************************/ void wDACbit(unsigned char Dbit) /* write bit */ { *(eth_data++) = DACoctet(nRS1, nLD1, nCS0, CLK0, Dbit); *(eth_data++) = DACoctet(nRS1, nLD1, nCS0, CLK1, Dbit); } int DACset(unsigned Abyte, unsigned Dbyte) { unsigned char *Start; int i; Start = eth_data; *(eth_data++) = 0; // temporary packet length *(eth_data++) = iniDAC; // define command *(eth_data++) = DACoctet(nRS1, nLD1, nCS1, CLK1, SDI1); // initial condition /* channel address */ for (i=0; i<2; i++) { unsigned char Dbit = (Abyte>>(1-i)) & 0x01; wDACbit(Dbit); } /* don't care */ for (i=0; i<2; i++) { unsigned char Dbit = (Abyte>>(1-i)) & 0x01; wDACbit(Dbit); } /* threshold value */ for (i=0; i<12; i++) { unsigned char Dbit = (Dbyte>>(11-i)) & 0x01; wDACbit(Dbit); } *(eth_data++) = DACoctet(nRS1, nLD1, nCS1, CLK1, SDI1); // end of transfer *(eth_data++) = DACoctet(nRS1, nLD0, nCS1, CLK1, SDI1); // activate settings *(eth_data++) = DACoctet(nRS1, nLD1, nCS1, CLK1, SDI1); // complete *Start = eth_data - Start; return (int)(eth_data - Start); } int DACres(void) { unsigned char *Start; Start = eth_data; *(eth_data++) = 0; // temporary packet length *(eth_data++) = iniDAC; // define command *(eth_data++) = DACoctet(nRS1, nLD1, nCS1, CLK1, SDI1); // initial condition *(eth_data++) = DACoctet(nRS0, nLD1, nCS1, CLK1, SDI1); // reset action *(eth_data++) = DACoctet(nRS1, nLD1, nCS1, CLK1, SDI1); // complete *Start = eth_data - Start; return (int)(eth_data - Start); } /***************************************/ /* ASIC configuration */ /***************************************/ void sASIC(void) /* start I2C transmission */ { *(eth_data++) = ASICoctet(31, RW1, SCL1, SDA1); *(eth_data++) = ASICoctet(31, RW0, SCL1, SDA0); *(eth_data++) = ASICoctet(31, RW0, SCL0, SDA0); } void wASICbit(unsigned char Dbit) /* write bit */ { *(eth_data++) = ASICoctet(31, RW0, SCL0, Dbit); *(eth_data++) = ASICoctet(31, RW0, SCL1, Dbit); *(eth_data++) = ASICoctet(31, RW0, SCL0, Dbit); } void wASICbyte(unsigned Dbyte) /* write byte */ { int i; for (i=0; i<8; i++) { unsigned char Dbit = (Dbyte>>(7-i)) & 0x01; wASICbit(Dbit); } } void aASIC(unsigned char MemA) /* write byte acknowledge */ { *(eth_data++) = ASICoctet(MemA, RW1, SCL0, SDA0); *(eth_data++) = ASICoctet(MemA, RW1, SCL1, SDA0); *(eth_data++) = ASICoctet(MemA, RW1, SCL0, SDA0); } void rASICbyte(unsigned char MemA) { unsigned char i; for (i=0; i<8; i++) aASIC(MemA+i); } void pASIC(void) /* terminate I2C transmission */ { *(eth_data++) = ASICoctet(31, RW0, SCL0, SDA0); *(eth_data++) = ASICoctet(31, RW0, SCL1, SDA0); *(eth_data++) = ASICoctet(31, RW0, SCL1, SDA1); *(eth_data++) = ASICoctet(31, RW1, SCL1, SDA1); } int ASICwrite(unsigned chipID, unsigned Pointer, unsigned *Value) { unsigned char *Start; Start = eth_data; *(eth_data++) = 0; // temporary packet length *(eth_data++) = iniASIC; // define command sASIC(); wASICbyte(chipID<<1 | 0); // write command aASIC(0); wASICbyte(Pointer); aASIC(1); if (Value) // not sending data from NULL address { wASICbyte( *Value); aASIC(2); } pASIC(); *Start = eth_data - Start; return (int)(eth_data - Start); } int ASICread(unsigned chipID, unsigned char Pointer) /* Write a pointer: ASICwrite(ChipID, Pointer, NULL) before reading command */ { unsigned char *Start; Start = eth_data; *(eth_data++) = 0; // temporary packet length *(eth_data++) = iniDAC; // define command sASIC(); wASICbyte(chipID<<1 | 1); // read command aASIC(0); // garbage collection rASICbyte(1); // push out byte wASICbit(0); // acknowledge pASIC(); *Start = eth_data - Start; return (int)(eth_data - Start); } /* ************* */ /* DEL controls */ /* ************* */ int DELset(unsigned Dbyte) { unsigned char *Start; int i; Start = eth_data; *(eth_data++) = 0; // temporary packet length *(eth_data++) = iniDEL; // define command *(eth_data++) = DELoctet(AE0, SC0, SI0); // initial condition *(eth_data++) = DELoctet(AE1, SC0, SI0); // initial condition for (i=0; i<8; i++) { unsigned char Dbit = (Dbyte>>(7-i)) & 0x01; *(eth_data++) = DELoctet(AE1, SC0, Dbit); *(eth_data++) = DELoctet(AE1, SC1, Dbit); } *(eth_data++) = DELoctet(AE0, SC0, SI0); *Start = eth_data - Start; return (int)(eth_data - Start); } /* ****************/ /* Visualisation */ /* ****************/ const char *byte_to_binary(unsigned char x) { static char b[9]; b[0] = '\0'; int i; for (i=256; i>0; i>>=1) strcat(b, ((x & i) == i) ? "1" : "0"); return b; } /***************************************/ /* Ethernet packet sender */ /***************************************/ void PING(int Device, int Address, int Command, int Dsize) { int i; ePackID = (rand()&0x7fff) | ((rand()&0x7fff)<<15); /* Re-build ethernet header */ dest_mac[0] = ( MCA<<4 | Device<<3 | LU)&0xFF; dest_mac[1] = (Address<<4 | Command)&0xFF; dest_mac[2] = (ePackID>>24)&0xFF; dest_mac[3] = (ePackID>>16)&0xFF; dest_mac[4] = (ePackID>>8)&0xFF; dest_mac[5] = (ePackID>>0)&0xFF; eCommID = dest_mac[0]<<8 | (dest_mac[1]&0xF3); memcpy((void *)eh->h_dest, (void*)dest_mac, ETH_ALEN); memcpy((void *)eh->h_source,(void*)src_mac, ETH_ALEN); /* Update data size */ eh->h_proto = htons(Dsize); /* Output data string */ i = sendto(s, buffer, (Dsize + ETHER_HDR_LEN), 0, ((struct sockaddr*)&socket_address), sizeof(socket_address)); if (i == -1) { perror("sendto():"); exit(1); } } /***************************************/ /* Ethernet packet receiver */ /***************************************/ int PONG(int Dsize) { int i; int TimeOut = 100; while(TimeOut) { unsigned CommID; unsigned PackID; /* Read NC buffer */ i = recvfrom(s, buffer, ETHER_MAX_LEN, 0, NULL, NULL); // Dsize (?) if (i == -1) { perror("recfrom():"); exit(1); } CommID = eh->h_source[0]<<8 | (eh->h_source[1]&0xF3); PackID = eh->h_source[2]<<24 | eh->h_source[3]<<16 | eh->h_source[4]<<8 | eh->h_source[5]; if ((CommID == eCommID)&&(PackID == ePackID)) break; TimeOut--; } /* end while(TimeOut) */ return TimeOut; } /***************************************/ /* Manage Configuration data */ /***************************************/ int Flush(int MBA, int Dsize) { /* Send configuration data */ PING(MB, MBA, Write, Dsize); /* allow sufficient time between sent packets (hardware needs 15ms to digest each of them) */ usleep(20000); /* reset pointer to beginning of the ethernet data field */ eth_data = buffer + ETH_HLEN; /* reset packet length counter */ return 0; } /***************************************/ /* Wait for trigger */ /***************************************/ int wTrig(void) { int Scale; /* Request MC read */ PING(MC, 0, Read, 38); /* pause between send and receive ethernet packets (hardware needs 10us to receive and to retransmit) */ usleep(20); /* Fetch MC data */ if (PONG(38)) { eth_data = buffer + ETH_HLEN; Scale = ((int)eth_data[8])<<24 | ((int)eth_data[9])<<16 | ((int)eth_data[10])<<8 | ((int)eth_data[11]); } else Scale = 0; return Scale; } /***************************************/ /* main module */ /* */ /* send configuration to motherboard N */ /***************************************/ int main(int argc, char **argv) { unsigned i, ind; unsigned ChipID, Nparam; unsigned Noctets = 0; int MBA; int Nevents = 0; char *Fname = "./teldat.bin"; if ((argc==2) | (argc==3)) Nevents = atoi(argv[1]); if (argc==3) Fname = argv[2]; /* Create socket */ eth_raw_init(); buffer = (void*)malloc(ETHER_MAX_LEN); /* set structurised pointer to beginning of ethernet header */ eth_head = buffer; eh = (struct ethhdr *)eth_head; /* Configure all boards */ for (MBA=0; MBA<5; MBA++) { /* set pointer to beginning of the ASIC conf. data */ unsigned *Value = MBset; printf("\n"); printf("Configure board %d:\n", MBA); /* set pointer to beginning of the ethernet data field */ eth_data = buffer + ETH_HLEN; /* Set control register */ if ((Noctets += CTRset( *Value++)) > ETH_SAFE_LEN) Noctets = Flush(MBA, Noctets); /* Set threshold DACs */ for (i=0; i<4; i++) if ((Noctets += DACset(i, *Value++)) > ETH_SAFE_LEN) Noctets = Flush(MBA, Noctets); /* Set ASIC 0 */ ChipID = *Value++; Nparam = *Value++; for (i=0; i ETH_SAFE_LEN) Noctets = Flush(MBA, Noctets); } /* end for Nparam */ /* Set ASIC 1 */ ChipID = *Value++; Nparam = *Value++; for (i=0; i ETH_SAFE_LEN) Noctets = Flush(MBA, Noctets); } /* end for Nparam */ /* Set delay */ if ((Noctets += DELset( *Value++)) > ETH_SAFE_LEN) Noctets = Flush(MBA, Noctets); /* Set latency */ if ((Noctets += LATset( *Value++)) > ETH_SAFE_LEN) Noctets = Flush(MBA, Noctets); /* Set event readout data length register */ if ((Noctets += RPLset( *Value++)) > ETH_SAFE_LEN) Noctets = Flush(MBA, Noctets); /* Put system in acquisition mode */ if ((Noctets += RUNgo()) > ETH_SAFE_LEN) Noctets = Flush(MBA, Noctets); /* Flush the rest for the given MBA */ if (Noctets) Noctets = Flush(MBA, Noctets); } /* end for(MBA) */ sleep(1); /* ------------ free of any obligations at this (.) */ /* external reset before taking data */ PING(MC, 0, Reset, 38); fp=fopen(Fname, "w+"); /* Event loop */ for (ind=0; ind>8) & 0xFF); Gevt[2] = (unsigned char)((ind>>16)& 0xFF); Gevt[3] = (unsigned char)((ind>>24)& 0xFF); fwrite(Gevt, 1, 4, fp); /* Extract temperatures */ Wpt = ð_data[12]; for (i=0; ih_source, 1, 6, fp); fwrite(eth_data, 1, RPlength, fp); } /* end if(PONG) */ } /* end for(MBA) */ /* external reset after each event */ PING(MC, 0, Reset, 38); } /* end for(Nevents) */ fclose(fp); return 0; } /* end main */ /***************************************/ /* eth_raw_init */ /***************************************/ int eth_raw_init() { int i; struct ifreq ifr; int ifindex = 0; // Ethernet Interface index /* Open socket */ s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (s == -1) { perror("socket():"); exit(1); } printf("Successfully opened socket: %i\n", s); /*Get ethernet interface index */ strncpy(ifr.ifr_name, DEVICE, IFNAMSIZ); if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) { perror("SIOCGIFINDEX"); exit(1); } ifindex = ifr.ifr_ifindex; printf("Successfully got interface index: %i\n", ifindex); /* retrieve corresponding MAC */ if (ioctl(s, SIOCGIFHWADDR, &ifr) == -1) { perror("SIOCGIFINDEX"); exit(1); } for (i=0; i<6; i++) src_mac[i] = ifr.ifr_hwaddr.sa_data[i]; printf("Host MAC address: "); for (i=0; i<6; i++) printf("%02X:", src_mac[i]); printf("\n"); /* prepare sockaddr_ll */ socket_address.sll_family = PF_PACKET; socket_address.sll_protocol = 0x00; socket_address.sll_ifindex = ifindex; socket_address.sll_pkttype = PACKET_BROADCAST; socket_address.sll_halen = ETH_ALEN; socket_address.sll_addr[0] = dest_mac[0]; socket_address.sll_addr[1] = dest_mac[1]; socket_address.sll_addr[2] = dest_mac[2]; socket_address.sll_addr[3] = dest_mac[3]; socket_address.sll_addr[4] = dest_mac[4]; socket_address.sll_addr[5] = dest_mac[5]; socket_address.sll_addr[6] = 0x00; socket_address.sll_addr[7] = 0x00; /* establish signal handler */ signal(SIGINT, sigint); printf("Established signal handler for SIGINT\n"); return 0; } /***************************************/ /* Socket Terminator */ /***************************************/ void sigint(int signum) { struct ifreq ifr; if (s == -1) return; // No socket has beeen created strncpy(ifr.ifr_name, DEVICE, IFNAMSIZ); ioctl(s, SIOCGIFFLAGS, &ifr); ifr.ifr_flags &= ~IFF_PROMISC; ioctl(s, SIOCSIFFLAGS, &ifr); close(s); free(buffer); fclose(fp); printf("Client terminating...\n"); exit(0); }