/////////////////////////////////////////////////////////////////////////// //// rs232_OEM_Universal.C //// //// //// //// Version for MBARI with special functions //// //// //// //// //// /////////////////////////////////////////////////////////////////////////// #include <18f26k20.H> #include #include #include #fuses EC #fuses NOMCLR #fuses PUT #fuses NOPROTECT #fuses NOBROWNOUT #fuses NOLVP #fuses NOWDT #use fast_io(A) #use fast_io(B) #use fast_io(C) #use delay(clock=16000000) #use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7) #define MBARI_PRE_SCANS 2 #define ReadoutsLow 0 #define ReadoutsHigh 1 #define IntPeriodL 2 #define IntPeriodM 3 #define IntPEriodH 4 #define SetEnables 5 #define SetIO 6 #define SetControlStrobe 7 #define SetStoreEnable 8 #define DataByte 0 #define TemperatureVals 3 #define StatusByte 1 #define HardTrig 1 #define SoftTrig 2 #define PixelSelect 7 #define PixelValue 9 #define DMAEnable 15 #define PCTrigger 14 #define LampStatus 1 #define ResetCircuit 13 #define DigitalRES 10 #define ChanellSelect 12 #define LoadDetectorWidth 12 #define SelectTempChannel 11 #define ConvertTemperature 12 #define Selector 12 #define SelectMonoColour 12 #define comma 0x2c #define cr 13 #define lf 10 #define eot 4 #define R 0x52 //#define S 0x53 #define G 0x47 #define F 0x46 #define T 0x54 //#define E 0x45 //#define P 0x50 #define D 0x44 #define H 0x48 #define A 0x41 #define K 0x4b #define W 0x57 #define Z 0x5a //#define B 0x42 //#byte PORTA = 5 //#byte PORTB = 6 #byte PORTA=0xf80 #byte PORTB=0xf81 #byte PORTC=0xf82 #define AddrStb PIN_A0 #define DataStb PIN_A1 #define EPPWr PIN_A2 #define StatusIn PIN_A3 //#define Wait PIN_A4 #define LED_RED PIN_A4 #define LED_GRN PIN_A5 #define ResetOut PIN_C3 #define CTS PIN_C4 #define RTS PIN_C5 #define TXD PIN_C6 #define ALL_IN 0xff #define ALL_OUT 0 #define BUFFER_SIZE 32 byte buffer[BUFFER_SIZE]; byte next_in = 0; byte next_out = 0; const char Date[15] = __DATE__; const char Time[15] = __TIME__; const char Revision[10] = "1.1"; int resolution, clk, Polling; int LampstatusRequired; long Readouts, Pixels; int index, Gain; int32 Period; char Command[10]; char SubString[10]; int measuring; int iStart; int Enabled; int high,low; long TempValue; int EnableRangeChange; int error; void EppAddrOut(char Addr) { set_tris_b(ALL_OUT); //data port output PORTB = Addr; // put addr on data bus Output_Bit(EPPWr,0); //EPP Write low Output_Bit(AddrStb,0); //Addr strobe low Output_Bit(AddrStb,1); //Addr strobe high Output_Bit(EPPWr ,1); //EPP Write high } void EppDataOut(char Data) { set_tris_b(ALL_OUT); //data port output PORTB = Data; // put data on data bus Output_Bit(EPPWr,0); //EPP Write low Output_Bit(DataStb,0); //Data strobe low Output_Bit(DataStb,1); //Data Strobe high Output_Bit(EPPWr,1); //EPP Write high } int8 EppDataIn() { int8 data; set_tris_b(ALL_IN); Output_Bit(EPPWr,1); //EPP Write high Output_Bit(DataStb,0); //Data strobe low data = PORTB; Output_Bit(DataStb,1); //Data Strobe high return Data; } #include "S3904256Params.c" void resetHardware() { Output_Bit(ResetOut,0); //send a hardware reset to 8452 (FLEX 6000A FPGA) Output_Bit(ResetOut,1); } void CameraWriteEnable() { EppAddrOut(SetStoreEnable); // delay_ms(1); EppDataOut(0); } void CameraPCTrigger() { EppAddrOut(PCtrigger); EppDataOut(0); } void SetReadouts() { Readouts = 1; //force readouts to always be one as a hack around the MBARIScan() int8 High, Low; High = Readouts >> 8; Low = Readouts; EPPAddrOut(ReadoutsLow); EPPDataOut(Low); EPPAddrOut(ReadoutsHigh); EPPDataOut(High); } void SetTimer(int32 Period) { int16 temp16; int High,Middle,Low; if (enabled != 0x10) { Period =(Period * ClkPeriodMultiplier) + PixelsToAdd; //8 microsecs clk } else { period = period; //if ext bunch trigger mode, 0x10, then count laser pulses not clk pulses } temp16 = period/256; high = temp16 / 256; middle = temp16; low = period; EPPAddrOut(IntPeriodL); EPPDataOut(Low); EPPAddrOut(IntPeriodM); EPPDataOut(Middle); EPPAddrOut(IntPeriodH); EPPDataOut(High); } void Type() { int temp; if (LampStatusRequired == 1) { EppAddrOut(LampStatus); Temp = Eppdatain() & 0x08; if (Temp == 0x08) resolution = 1; else resolution = 0; // resolution = 1 lamp = ON else Lamp = off LampStatusRequired = 0; } else if (polling == 0) // normal output of camera properties { Resolution=InitResolution; // resolution = 12 or 16 Clk=InitClk; // clk = 1, 2, 4, 8 or 16 } else // report readout status via resolution value 1 = not finished 0 = finished { if (INPUT(StatusIn) == 1) { resolution = 1; //finished high not complete } else { resolution = 0; // finished low readout done polling = 0; // } // printf("%Lu %U %U \r",Pixels,resolution,clk); } printf("%Lu %U %U \r",Pixels,resolution,clk); } void Version() { printf("MBARI-ISUS %s, %s, %s\n\r", Revision, Date, Time); } void GetSubString() { int x; x = iStart + 1; //After first char in command comes the value strcpy(SubString,&Command[x]); } void printdone() { printf("Done\r"); } void DoneMeasurement() { if ( INPUT(StatusIn) == 1 ) printf("NDONE\r"); else printf("DONE\r"); } void Measure() { CameraWriteEnable(); While ( INPUT(StatusIn) == 0 ); // finished signal is low before going high during scan } void TriggerReadouts1() { CameraWriteEnable(); While ( INPUT(StatusIn) == 0 ); // finished signal is low before going high during scan While ( INPUT(StatusIn) == 1 ); // wait for finished to go low again printdone(); } void TriggerReadouts2() { CameraPCTrigger(); //trigger one readout While ( INPUT(StatusIn) == 1 ); // finished signal is low before going high during scan While ( INPUT(StatusIn) == 0 ); // wait for finished to go low again } void TriggerReadouts3() // used enable trigger mode 0x80 to trigger readout { CameraWriteEnable(); While ( INPUT(StatusIn) == 0 ); // finished signal is low before going high during scan Polling = 1; } /******************************************************************************/ /* Device is triggered either internally or via a software command. A value of*/ /* 0x01 sets the device for internal "self-triggering", a value of 0x02 sets */ /* the device for "software-triggering" */ /* If device is configured for internal triggering then after the number of */ /* programmed readouts has occured, pin 12 will return low, it goes high */ /* after the first trigger of the sequence. If however the device is */ /* configured for external or software triggering then pin 12 functions as an */ /* indicator of the diode array scan period, when low the array is being */ /* scanned upon returning high the diode array scan period has finished (4ms) */ /******************************************************************************/ void MBARIScan() { int8 i; output_bit(RTS,0); //assert RTS, let the controller know we're now scanning output_bit(LED_GRN, 0); EppAddrOut(SetEnables); // put electronics into E2 "PC" trigger mode EppDataOut(2); EppAddrOut(PCtrigger); for(i=1; i <= MBARI_PRE_SCANS; i++) //clear the array of any residual charge { EppDataOut(0); while( INPUT(StatusIn) == 1 ); //wait for the Status Pin to go low while( INPUT(StatusIn) == 0 ); //wait for the Status Pin to go high } EppDataOut(0); for(i=1; i <= Readouts; i++) //loop Readout times to get spectrum { delay_ms(Period); //wait the preset integration time EppAddrOut(SetStoreEnable); //enable data storage EppDataOut(0); EppAddrOut(PCtrigger); EppDataOut(0); } delay_ms(5); //wait for detector to finish last scan output_bit(RTS,1); //unassert RTS, let the controller know we're now done (controller should monitor RTS for hung condition and timeout) output_bit(LED_GRN, 1); // printdone(); } void LEDs() { int state; GetSubString(); state=atoi32(SubString); switch (state) { case 1: output_bit(LED_GRN, 1); break; case 2: output_bit(LED_GRN, 0); break; case 3: output_bit(LED_RED, 1); break; case 4: output_bit(LED_RED, 0); break; default: break; } } void Start() { if (enabled != 0) { switch (Enabled) { case 1: TriggerReadouts1(); break; // case 2: TriggerReadouts2(); break; case 4: TriggerReadouts1(); break; //for external trigger, just enable data store. Wait for finished case 8: MBARIScan(); break; //Special procedure for MBARI case 16: TriggerReadouts1(); break; //MUltiple laser trigger default: printf("E:%s\r",command); } } else printf("E:%s\r",command); // no trig mode enabled } void ProgPixels(int loc, long TempValue) { int High,Low; if (Resolution != 8) TempValue = TempValue * 2; High = TempValue >> 8; Low = TempValue; EPPAddrOut(PixelSelect); EPPDataOut(loc); EPPAddrOut(PixelValue); EPPDataOut(low); loc = loc + 1; EPPAddrOut(PixelSelect); EPPDataOut(loc); EPPAddrOut(PixelValue); EPPDataOut(high); } void IOOut(int Value) { EppAddrOut(SetIO); EppDataOut(Value); LampStatusRequired = 1; } void Enables() { //int index, Gain; GetSubString(); index=atoi32(SubString); enabled = 1; switch (index) { case 0: index=0; enabled = 0; break; // enable nothing case 1: index=1; enabled = 1; break; // enable Int timer trig case 2: index=2; enabled = 2; break; // enable PC trig case 3: index=4; enabled = 4; break; // enable Ext trig case 4: index=0x11; enabled = 0x10; break; // enable Ext bunch trig ie multiple laser pulses case 5: index=2; enabled = 8; break; // enable group trig case 64: Gain = 0; break; case 65: Gain = 0x80; break; case 128: triggerReadouts3(); break; // use enable trigger mode 0x80 to trigger readout case 130: IOOut(0); break; case 131: IOOut(1); break; case 132: IOOut(2); break; case 133: IOOut(3); break; default: index=0; enabled = 0; } if (index < 128) { EppAddrOut(5); EppDataOut(index | Gain); //gain bit is at D7 SetTimer(Period); } //printf("Q %U\r",index); } void GetIntPeriod() { GetSubString(); Period = atoi32(SubString); SetTimer(Period); } void GetReadouts() { GetSubString(); Readouts = atol(SubString); SetReadouts(); } void SetUart(int b) { switch(b) { case 0x1: Set_uart_speed(9600); break; case 0x2: Set_uart_speed(19200); break; case 0x3: Set_uart_speed(38400); break; case 0x4: Set_uart_speed(57600); break; case 0x5: Set_uart_speed(115200); break; default: Set_uart_speed(9600); break; //if eeprom not set start at 9600 } } void SetCommSpeed() { int32 b; int c; GetSubString(); b = atoi32(SubString); c = b; SetUart(c); write_eeprom(0,c); } void ReadBack() { GetSubString(); } #int_rda void serial_isr() { buffer[next_in]=getc(); if (measuring == 1) if (buffer[next_in]!= 10) { resetHardware(); } next_in=(next_in+1) % BUFFER_SIZE; } void SetDataFormat() { GetSubString(); Format = SubString[0]; write_eeprom(1,Format); } void OutputByteFormat() { int8 high_b, low_b; int16 x; output_bit(RTS,0); //signal program it's time to start burping the data out for (x = 1; x <= Pixels; x++) { high_b = Eppdatain(); low_b = EppDatain(); while( input(CTS) ); //wait for CTS input to go low putc( high_b ); putc( low_b ); } output_bit(RTS,1); //signal program we're done burping the data out } void OutputWordFormat() { int8 high_b, low_b; int16 x, result; output_bit(RTS,0); //signal program it's time to start burping the data out for (x = 1; x <= Pixels; x++) { high_b = Eppdatain(); low_b = EppDatain(); result = high_b << 8; result = result + low_b; while ( input(CTS) ); //wait for CTS input to go low if( Format == 0x31 ) //unsigned 16bit value in decimal with CR printf("%Lu\n\r", result); else if( Format == 0x32 ) //unsigned 16bit value in hexidecimal with CR printf("%Lx\n\r", result); else{ //unsigned 16bit value in decimal with Format char if( x != Pixels ) printf("%Lu%C", result, Format); else printf("%Lu\n\r", result); } } output_bit(RTS,1); //signal program we're done burping the data out } void GetData() { EppAddrOut(DataByte); if (Format == 0x30) //send pixel A/D counts as two binary bytes OutputByteFormat(); else //send pixel A/D counts as decimal or hexidecimal ASCII value OutputWordFormat(); } void GetDataSingleValue() { int8 y; int16 x; EppAddrOut(DataByte); //Data port output_bit(RTS,0); //signal program in time to start burping the data out output_bit(LED_RED, 0); for(x=1; x <= 512; x++) { while (input(CTS)); //wait for CTS input to go low y = Eppdatain(); putc(y); output_toggle(LED_RED); while (!input(CTS)); ///wait for CTS input to go high } output_bit(RTS,1); //signal program we're done burping the data out output_bit(LED_RED, 1); } void GetString() { char c; next_out = 0; c = 0; while(c != 13) { if (next_in > next_out) { c = buffer[next_out]; command[next_out]= c; next_out=(next_out+1) % BUFFER_SIZE; } } command[next_out]=0; next_in = 0; } void GetValue() { GetSubString(); Tempvalue=atol(SubString); } void EchoCommand() { if (error == 1) { PUTC(0x45); // send E PUTC(0x3A); // send : error = 0; } Printf("%s\r",Command); } int ReadEEPROM(int loc) { int Data; Data=read_eeprom(loc); return data; } void RangeChange() { GetSubString(); Tempvalue=atol(SubString); if (Tempvalue == 1919) EnableRangeChange = 1; } void SetPixelStart() { if (EnableRangeChange == 1) { GetValue(); ProgPixels(0,TempValue); High = TempValue >> 8; Low = TempValue; write_eeprom(8,low); write_eeprom(9,high); StartPixel = TempValue; Pixels = (EndPixel - StartPixel); // + 9;// 9 dark pixels } else error = 1; EnableRangeChange = 0; } void SetPixelEnd() { if (EnableRangeChange == 1) { GetValue(); ProgPixels(2,TempValue); High = TempValue >> 8; Low = TempValue; write_eeprom(10,low); write_eeprom(11,high); endPixel = TempValue; Pixels = (EndPixel - StartPixel);// + 9;// 9 dark pixels } else error = 1; EnableRangeChange = 0; } void GetCommand() { char cmd; GetString(); iStart = 0; while(!isalnum(Command[iStart])) ++iStart; //cmd = TOUPPER(Command[iStart]); cmd = Command[iStart]; switch (cmd) { case 'I': GetIntperiod(); EchoCommand(); break; case R: GetReadouts(); EchoCommand(); break; case 'S': Start(); break; case 's': Start(); break; case 'G': GetData(); break; case 'g': GetDataSingleValue(); break; case 'T': Type(); break; //pixels, resolution, clk case 'V': Version(); break; //firmware version and compilation timestamp case 'L': LEDs(); break; case 'E': Enables(); EchoCommand(); break; case 'B': GetSubString(); Printf(SubString); break; //ASCII B case F: SetDataFormat(); EchoCommand(); break; case A: SetCommSpeed(); EchoCommand(); break; case W: SetPixelStart(); EchoCommand(); break; //only using DoExtendedInstruction case Z: SetPixelEnd(); EchoCommand(); break; //only using DoExtendedInstruction case D: DoneMeasurement(); break; //Just for Stellarnet case 'M': Measure(); EchoCommand(); break; //Just for Stellarnet case H: RangeChange(); EchoCommand(); break; default: printf("V:%s",command); } } void StartUpReset() { EppAddrOut(SetStoreEnable); //enable data storage EppDataOut(0); delay_ms(20); //wait for one readout EppAddrOut(DataByte); //get one byte of data, will reset address pointer EppDataIn(); } void main() { delay_ms(100); //give PLD time to load configuration from EEPROM clk = read_eeprom(0); //retrieve desired baud rate Format = read_eeprom(1); //retrieve desired data format, this value was getting clobered by init() so I commented out Format = 0x30 in the S3904256Params.C file // SetUart(clk); //don't bother as we will use the default set by: use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7) // SET_TRIS_A(0x18); //A0, A1, A2 output A3, A4 input set_tris_a(0x08); //A0, A1, A2 output A3 input, A4, A5 output SET_TRIS_C(0x97); //C7 = RX & C4 = CTS set input C6 = TX & C5 RTS Set output PORT_B_PULLUPS(true); output_bit(RTS,0); //set RTS output low, let the controller know we're initializing Setup_Timer_0(0); set_tris_b(ALL_OUT); //data port output Output_Bit(AddrStb,1); //Addr Strobe high Output_Bit(DataStb,1); //Data Strobe high Output_Bit(EPPWr,1); //EPP Write high resetHardware(); Enabled = 0; Readouts = 1; //for starters Period = 1; PORTB = 0xff; ENABLE_INTERRUPTS(GLOBAL); ENABLE_INTERRUPTS(INT_RDA); EppAddrOut(ResetCircuit); EppDataOut(0); //reset hardware Finished signal low. init(); //see S3904256Params.C file, Format = 0x30 has been commented out SetTimer(1); SetReadouts(); polling = 0; LampStatusRequired = 0; StartPixel = 1; ProgPixels(0,StartPixel); EndPixel = 257; ProgPixels(2,EndPixel); Pixels = (EndPixel - StartPixel); //+ 9; // dark value pixels Enabled = 0; Gain = 0; EppAddrOut(SetEnables); EppDataOut(1); //EppDataOut(2); StartUpReset(); //perform a simple one byte read to reset the PLD SRAM memory pointer, which seems to develop a one pixel offset after the first power-on measurement cycle output_bit(RTS,1); //clear RTS, let the controller know we're now done (controller should monitor RTS to validate power up) output_bit(LED_RED, 1); output_bit(LED_GRN, 1); //turn off for now, LED is wired backwards. while(1) //loop forever { GetCommand(); } } //end main()