/* VME MONITORING PROGRAM*/ // RELEASE VERSION 2 // DATE JULY 2ND 2003 // PROJECT LOCATION: \\IFAE-P10\Readout Buffers\Fw2003\Rb.prj // FILENAME: RB2.C (VERSION WITH DUMP MODE // EF_FIN -> DATA0 // HF_FOUT -> DATA1 // FF_FOUT -> DATA2 //*************************************************************************************** VARIABLES MAINTAINED #pragma DEBUG OBJECTEXTEND CODE #include #include #include #include "CAN.H" #define EOC 0xAA #define C1 1 #define C2 2 #define C3 3 #define C4 4 #define BYPASS 1 #define START 2 #define STOP 3 #define SEND 4 #define MASK 5 #define RIMR 6 #define RECV 7 #define TIMER 8 #define AUTOSEND 9 #define NOTIMER 10 #define CHECKDESCR 11 #define SETDESCR 12 #define ENABLE 13 #define SYNCRO 14 #define DUMP 15 #define FASTDUMP 16 #define SETDUMPMODE 17 xdata unsigned char wr_fout _at_ 0xB000; /* DATA FROM CAN TO VME */ xdata unsigned char mr_fout _at_ 0xB001; /* RESET FIFO FROM CAN TO VME */ xdata unsigned char rd_fin _at_ 0xA000; /* FIFO IN DATA REGISTER */ xdata unsigned char f_state _at_ 0x9000; /* FIFO IN/OUT STATUS */ data unsigned char autotrig; data unsigned char divH; data unsigned char divL; data unsigned char irqmask; data unsigned char shadowmemdump; data unsigned char mode; // Dump mode flag (0==OFF,1==ON, OFF==DEFAULT) extern asmdump(); extern fastdump(); void main(void) { // COMMAND FRAMES FORMAT data unsigned char command; // COMMAND FIELD = FIRST FIELD data unsigned char channel; // CHANNEL FIELD = SECOND FIELD data unsigned char length; // LENGTH FIELD = NUMBER OF FOLLOWING DATA data unsigned char dat[31]; // DATA FIELD = NUMBER OF BYTES IS DEFINED BY LENGTH FIELD data unsigned char i; // DEFAULT PARAMETERS irqmask = 0x00; // FOUR CHANNELS ARE DISABLED autotrig = 0x00; // NO AUTOTRIGGER divH = 0x00; // NO TIMER divL = 0x00; // NO TIMER mode = 0x00; // DUMP MODE IS OFF BY DEFAULT // CONFIGURE RD AND WR FOR EXTERNAL DATA ACCESS P1 = 0xFF; // ENABLE 4 MSB AS INPUTS (INT_Cx) AND 4 LSB AS OUTPUTS NOT ASSERTED (CAN_RST*) P3 = 0xE4; // RD AND WR CONTROLLED FROM C501, AUX0 AUX1 AND IRQ0 AS INPUT // Enable IRQ source 0 to receive messages from CAN IT0 = 0; EX0 = 1; // ENABLE EXTERNAL INTERRUPT CALL 0 EA = 1; // DISABLE IRQ WIDE MASK IP = IP | 0X01; // HIGH PRIORITY ON /INT0 // START MAIN LOOP // LOOK FOR INCOMING MESSAGES FROM CAN // LOOK FOR INCOMING COMMANDS FROM VME mr_fout=0x00; // RESET FIFO OUT // START TO PROCESS COMMANDS FOREVER while (1) { if ( (f_state & 0x01) == 1 ) // LOOK AT THE FIFO STATE { // PROCESS THE INCOMING COMMANDS HERE // RECOVER THE COMMAND command = rd_fin; // RECOVER THE COMMAND CODE while ( (f_state & 0x01) == 0 ); // WAIT FOR NEXT BYTE channel = rd_fin - 1; // RECOVER THE CHANNEL CODE while ( (f_state & 0x01) == 0 ); // WAIT FOR NEXT BYTE length = rd_fin & 0x1F; // RECOVER LENGTH CODE AND PROTECT AGAINST TOO LONG LENGTH CODES for (i=0;i> 13) & 0x07); // ID HIGH wr_fout = (unsigned char)((CAN[channel].DESCRIPTOR[15] >> 5 ) & 0xFF); // ID LOW wr_fout = (unsigned char)((CAN[channel].DESCRIPTOR[15] ) & 0x0F); // DLC for (i=0;i<8;i++) { wr_fout = CAN[channel].Msg[15].Byte[i]; } break; case SETDESCR: CAN[channel].DESCRIPTOR[dat[0]] = ( (dat[1]&0x07)<<13) | (dat[2] << 5) | (dat[3]&0x0F) ; // BUFFER 0 for (i=1;i<8;i++) CAN[channel].Msg[dat[0]].Byte[i] = dat[i+4]; CAN[channel].Msg[dat[0]].Byte[0] = dat[4]; // Dump shadow memory break; case DUMP: while( (f_state & 0x02) == 0); // WAIT FOR FREE SPACE IN FIFO_OUT wr_fout = DUMP; // SEND COMMAND CODE // Dump the four CAN Controllers whole registers asmdump(); break; case FASTDUMP: while( (f_state & 0x02) == 0); // WAIT FOR FREE SPACE IN FIFO_OUT wr_fout = FASTDUMP; // SEND COMMAND CODE // Dump the four CAN Controllers whole registers fastdump(); break; case SETDUMPMODE: // MODE = 0 --> IRQs will push RECV commands into FIFO_OUT // MODE = 1 --> IRQs will push FASTDUMP commmands into FIFO_OUT mode = (unsigned char)(dat[0])&0x01; break; } // END OF SWITCH } else // IF NO VALID EOC { // SYNCHRO mr_fout = 0x00; // RESET FIFO OUT wr_fout = SYNCRO; // COMMAND IS SYNCHRO wr_fout = 0x00; // CHANNEL IS 0 wr_fout = 0x00; // THERE IS NO DATA } } // END OF VME COMMANDS IF STATEMENT } // END WHILE(1) } // END MAIN //************* INTERRUPTS SERVICE ROUTINES */ void CAN_AUTOTRIG (void) interrupt 3 { // RELOAD THE TIMER 1 // SET TRANSMIT REQUEST BIT OF MSG 15 OF THE CAHNNEL SET TO 1 IN AUTOTRIG REGISTER TH1 = divH; TL1 = divL; // RELOAD THE TIMER if ( ( autotrig & 0x01 ) == 0x01) CAN[0].TRS2 = 0x80; if ( ( autotrig & 0x02 ) == 0x02) CAN[1].TRS2 = 0x80; if ( ( autotrig & 0x04 ) == 0x04) CAN[2].TRS2 = 0x80; if ( ( autotrig & 0x08 ) == 0x08) CAN[3].TRS2 = 0x80; } void CAN_COMMAND (void) interrupt 0 { // PROCESS THE INCOMING CAN DATA HERE // CAN DATA IS ANNOUCED BY IRQ0 ASSERTION // THEN DECODE WHICH CHANNEL CAUSED THE IRQ0 // THEN RECOVER THE FRAME AND PUSHES IT INTO FIFO OUT unsigned char irqsource; unsigned char i,j,k,x,msg; if (mode == 0) { // DECODE IRQ SOURCE irqsource = P1; irqsource = (irqsource >> 4) | !irqmask; // TO DISABLE IRQ SOURCE ALWAYS ADD 1 TO THE BIT LOCATION ASSIGNED k=0x08; // POLL THE FOUR CANBUS INTERRUPT SOURCES for (j=0;j<4;j++) { // TEST THE CURRENT PORT if ( (irqsource & k) == 0x00) { // IS THERE ANY NEW MESSAGE HERE? if ( CAN[j].RRR1 != 0x00 ) { // NEW MESSAGES HERE x=0x01; // FIRST MESSAGE POINTER for (msg=0;msg<8;msg++) { if ((CAN[j].RRR1 & x) == x) { shadowmemdump = CAN[j].Msg[msg].Byte[7]; wr_fout = RECV; // RECEIVE COMMAND wr_fout = j+1; // Channel number wr_fout = 11; // Fixed length wr_fout = (unsigned char)((CAN[j].DESCRIPTOR[msg] >> 13) & 0x07); // ID HIGH wr_fout = (unsigned char)((CAN[j].DESCRIPTOR[msg] >> 5 ) & 0xFF); // ID LOW wr_fout = (unsigned char)((CAN[j].DESCRIPTOR[msg] ) & 0x0F); // DLC for (i=0;i<8;i++) wr_fout = CAN[j].Msg[msg].Byte[i]; CAN[j].RRR1 &= (~x); } x = x*2; // NEXT MESSAGE POINTER } } if ( CAN[j].RRR2 != 0x00 ) { // NEW MESSAGES HERE x=0x01; // FIRST MESSAGE POINTER for (msg=8;msg<16;msg++) { if ((CAN[j].RRR2 & x) == x) { shadowmemdump = CAN[j].Msg[msg].Byte[7]; wr_fout = RECV; // RECEIVE COMMAND wr_fout = j+1; // Channel number wr_fout = 11; // Fixed Length wr_fout = (unsigned char)((CAN[j].DESCRIPTOR[msg] >> 13) & 0x07); // ID HIGH wr_fout = (unsigned char)((CAN[j].DESCRIPTOR[msg] >> 5 ) & 0xFF); // ID LOW wr_fout = (unsigned char)((CAN[j].DESCRIPTOR[msg] ) & 0x0F); // DLC for (i=0;i<8;i++) wr_fout = CAN[j].Msg[msg].Byte[i]; CAN[j].RRR2 &= (~x); } x = x*2; // NEXT MESSAGE POINTER } } CAN[j].INT = 0; // RESET IRQ BIT } // END IF IRQSOURCE k = k/2; // NEXT PORT } // END FOR } else if (mode == 0x01) // FASTDUMP MODE { while( (f_state & 0x02) == 0); // WAIT FOR FREE SPACE IN FIFO_OUT wr_fout = FASTDUMP; // SEND COMMAND CODE // Dump the four CAN Controllers whole registers fastdump(); // Clear interrupts flags for (j=0;j<4;j++) { CAN[j].RRR1 = 0x00; CAN[j].RRR2 = 0x00; CAN[j].INT = 0x00; } } IE0 = 0; // RESET IRQ0 BIT OF C51 }