//============================================================================ // // N O R S T A R S i m u l a t o r p r o g r a m // // For RV "POLARSTERN" seismic survey August 2003. // // It is assumed that the interface box labelled "ITEM 20" is // connected to the laptop computer running this program. A 1-to-1 // paralell cable must be used. // // When the program detects signal from Polarstern Gun controller (HIGH TTL // pulse) is sends NORSTAR serial string and CLOSURE IN signal to // Streamer Interface Box. This signal can be simulated by pressing 'T'. // // TRIACQ must be set to start recording after reception of // NORSTAR serial data and CLOSURE IN signal. // // NORSTAR data is time stamped (Year, Julian day, Hour, Minutes // and Seconds) and also event number (shot counter). All other // data fields in the NORSTAR telegram should be disregarded. A valid // checksum is generated. Time and date is read from PC clock. // // Shot number and time stamp is written to screen for each shot. // These values are also logged to file on this computer. // Filename is generated automatically and reflects date and time // the file was created. // // Documentation on this web page: // http://www2.geo.uib.no // // // Rev. Date By Description // ----------------------------------------------- // 0.1 6 Aug 2003 KH/EG/OM Test version // //============================================================================ #include #include #include #include #include #include #include #include #include #include #include // C o n s t a n t s #define lptPORTADDRESS 0x378 #define DATA lptPORTADDRESS+0 #define STATUS lptPORTADDRESS+1 #define CONTROL lptPORTADDRESS+2 #define PULSEWIDTH_T1 10 //Clusure In (to Streamer Interface) #define PULSEWIDTH_T4 10 //FTB (to Streamer Interface) #define WAITTIME_T4 128 //Delay from Blast (T3) to FTB (T4) // T y p e d e c l a r a t i o n s struct Norstar4 { unsigned short identity; unsigned short length; unsigned int shotPoint; double shotTime; short shotIncrement; unsigned short shotFlag; unsigned short relayMode; unsigned short lineMode; unsigned short year; unsigned short julianDay; unsigned short hour; unsigned short minutes; unsigned short seconds; unsigned short fraction; char clientName[16]; char lineName[16]; char jobName[16]; char areaName[16]; char vesselName[16]; float centralMeridian; double inverseFlattening; double majorAxis; unsigned short numberOfPositions; // These values does not need change. char pos1[44]; char pos2[44]; // This checksum should probably be calculated somewhere.. unsigned short checksum; }; //========================================================== // Generate a checksum //========================================================== unsigned short generate_checksum(Norstar4 *dataset) { struct mks { unsigned short words[114]; }; mks *mk_checksum; unsigned short checksum_tmp=0; mk_checksum = (mks*)dataset; checksum_tmp = mk_checksum->words[0]; for (int a=1; a<113; a++) { checksum_tmp = checksum_tmp xor mk_checksum->words[a]; } dataset->checksum = checksum_tmp; } //========================================================== // Leapyear detection //========================================================== int is_leapyear(int year) { return ( (!(year%4)) && ( (year%100) || (!(year%400)) ) ); } //========================================================== // Calculate Julian day //========================================================== int day_of_year(int date, int month, int year) { short d[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; short temp_a; short temp_b = 0; if ( (date<1) || (date>31) || (month<1) or (month>12) ) return 0; if (is_leapyear(year)) d[1]++; for (temp_a=0; temp_a<(month-1); temp_a++) { temp_b += d[temp_a]; } temp_b += date; return temp_b; } //=============================================== // M A I N P R O G R A M //=============================================== unsigned char dummybyte; unsigned int shotno; bool done; bool soft_trigger; char kbcharacter; short day_no; bool idle_state = false; // For a signal to be accepted, it must first // be in idle state (idle_state = true), // after that is must be in active state (edge detection). int main(int argc, char *argv[]) { Norstar4 dataset; FILE *gf; // get from file FILE *pf; // put to file (COM1) FILE *logfile; // log events to file char logfilename[13]; time currentTime; date currentDate; // Open the file where we find an example NORSTAR data set. // Later we will change date, time and shot number, and generate // new checksum. gf = fopen("norstar.dat", "rb"); // Seek to a position fseek(gf, 0, SEEK_SET); // Read a single dataset fread(&dataset, sizeof(dataset), 1, gf); fclose(gf); // open log file gettime(¤tTime); getdate(¤tDate); sprintf(logfilename, "%02d%02d%02d%02d.%02d", currentDate.da_mon, currentDate.da_day, currentTime.ti_hour, currentTime.ti_min, currentTime.ti_sec ); logfile = fopen(logfilename, "w"); fprintf(logfile, "ShotNo. Year-Month-Day JulianDay Hour:Min:Sec\n"); // set shotnumber to start on shotno = 1; clrscr(); printf("N O R S T A R S I M U L A T O R\n"); printf("\nPress (and hold a bit) 'T' to test trigging, 'Q' to quit.\n\n"); // Open COM1 pf = fopen("COM1", "wb"); soft_trigger = false; //----------------------------------------------- // M a i n l o o p //----------------------------------------------- while (!done) { //outportb(DATA, ~inportb(DATA)); //Test, can use oscilloscope to time the loop ... if ( !(inportb(STATUS) & 0x40) ) // Idle state? { idle_state = true; if (kbhit()) // Check for keyboard soft trigger { kbcharacter = getch(); if ((kbcharacter == 't') || (kbcharacter == 'T')) soft_trigger = true; kbcharacter = 0; } } if (( (inportb(STATUS) & 0x40) && idle_state ) || soft_trigger ) // Now Active state? { //------------------------------------------------ // Trigger signal from POLARSTERN GUNCO detected // Start firing sequence //------------------------------------------------ idle_state = false; // Flag reset soft_trigger = false; //---------------------------------------------------- // NORSTAR SERIAL OUTPUT //---------------------------------------------------- // Timestamp and stuff // use ntohs, htons, ntohl, htonl for converting endians gettime(¤tTime); getdate(¤tDate); dataset.hour = htons(currentTime.ti_hour); dataset.minutes = htons(currentTime.ti_min); dataset.seconds = htons(currentTime.ti_sec); dataset.shotPoint = htonl(shotno); dataset.julianDay = htons(day_of_year(currentDate.da_day, currentDate.da_mon, currentDate.da_year)); generate_checksum(&dataset); printf("Shot nr: %d Date: %04d-%02d-%02d Julian day: %3d Time: %02d:%02d:%02d\n", shotno, currentDate.da_year, currentDate.da_mon, currentDate.da_day, ntohs(dataset.julianDay), currentTime.ti_hour, currentTime.ti_min, currentTime.ti_sec); // Write to COM port printf("Writing dataset to COM1\n"); //printf("Day no.: %d\n", dataset.julianDay); fwrite(&dataset, sizeof(dataset), 1, pf); fflush(pf); // write to logfile printf("Writing to logfile\n"); fprintf(logfile, "%d %04d-%02d-%02d %3d %02d:%02d:%02d\n", shotno, currentDate.da_year, currentDate.da_mon, currentDate.da_day, ntohs(dataset.julianDay), currentTime.ti_hour, currentTime.ti_min, currentTime.ti_sec); fflush(logfile); shotno++; //---------------------------------------------------- // Send 'CLOSURE IN' signal to Streamer Interface Box //---------------------------------------------------- outportb(DATA, inportb(DATA) & 0xFD); // Start of 10ms closure (T1) delay(PULSEWIDTH_T1 - 0); outportb(DATA, inportb(DATA) | 0x02); //---------------------------------------------------------- // N O T E // As University of Bergen TRIACQ was not working properly // the following section could not be tested and is // therefore not used (commented out). // POLARSTERN TRIACQ must then be configured to start // recording after reception of CLOSURE IN signal to // Streamer Interface Box. // ######## START OF OMITTED SECTION ######### /* //---------------------------------------------------------- // Wait for 'CLOSURE OUT' signal from Streamer Interface Box //---------------------------------------------------------- // Wait for Closure Out (T2) printf("Waiting for Closure Out\n from Streamer Interface at T2\n"); printf("(Hit '2' to skip this and move on...)\n"); //while( (inportb(STATUS) & 0x80) && !done ) while( !( done || (idle_state && !(inportb(STATUS)&0x80)) ) ) { //idle_state = (inportb(STATUS) & 0x80); if (inportb(STATUS) & 0x80) idle_state = true; if (kbhit()) //done = true; kbcharacter = getch(); if (kbcharacter == '2') done = true; kbcharacter = 0; } if (!done) { gotoxy(wherex(),wherey()-1); printf("Closure received at T2 \n"); } done = false; idle_state = false; //---------------------------------------------------------- // Wait for 'BLAST OUT' signal from Streamer Interface Box //---------------------------------------------------------- // Wait for Blast Signal (T3) printf("Waiting for Blast signal\n from Streamer Interface at T3\n"); printf("(Hit '3' to skip this and move on...)\n"); while( !( done || (idle_state && (inportb(STATUS)&0x20)) ) ) { //idle_state = !( inportb(STATUS) & 0x20 ); if ( !( inportb(STATUS) & 0x20 ) ) idle_state = true; if (kbhit()) { kbcharacter = getch(); if (kbcharacter == '3') done = true; kbcharacter = 0; } } if (!done) { gotoxy(wherex(),wherey()-1); printf("Blast signal received at T3 \n"); } done = false; idle_state = false; // Wait 128ms delay(WAITTIME_T4 - 0); //---------------------------------------------------------- // Send 'FTB IN' signal to Streamer Interface Box //---------------------------------------------------------- // Generate 10ms FTB (T4) outportb(DATA, inportb(DATA) & 0xFE); delay(PULSEWIDTH_T4 - 1); outportb(DATA, inportb(DATA) | 0x01); */ // ####### END OF OMITTED SECTION ####### // Information printf("Shot sequence OK, waiting for next trigger...\n\n"); // Pause to prevent re-trigging: //delay(222); //not needed when edge trigging introduced } // End of if(triggesignal...) if (kbhit()) { kbcharacter = toupper(getch()); if (kbcharacter == 'Q') done = true; kbcharacter = 0; } } // End of while(!done) fclose(pf); fclose(logfile); printf("\nExit from program...\n\n"); return 0; }