/* Test Code to make Arduino Ethernet communicate with PLD of Volker Commichaus Bias Crate Controller of the FACt Bias voltage supply system instead of FT245R interface Interface to PLD or something that behaves similarly: Digital I/O: Arduino Pin : Net Name : Int/Out/Bi : mnemonic ----------------------------------------------------------------------------- Pin D2 : WR : I : Write to 'FIFO' Pin D3 : RD# : I : Read from 'FIFO' Pin D8 : TXE# : O : transmit enable Pin D9 : RXF# : O : Read from FIFO possible Pin D4 : D0 : BI Pin D5 : D1 : BI Pin D6 : D2 : BI Pin D7 : D3 : BI Pin A0 : D4 : BI : Data Pin A1 : D5 : BI Pin A2 : D6 : BI Pin A3 : D7 : BI ----------------------------------------------------------------------------- port definition: Port D consists of Arduino-Pins 0 - 7 and is used for Data exchange with the PLD Port C consists of Arduino-Pins A0 - A5 and is used for Data exchange with the PLD */ //define non transferable variables #define MAXBOARDS 13 #define EXISTINGBOARDS 10 #define CHPERBOARD 32 #define NUMCHANNELS EXISTINGBOARDS*CHPERBOARD #define BLANKBYTE 0x00 #define READSTATEBYTE 0x20 #define GLOBALSETBYTE 0x40 #define CHANNELSETBYTE 0x60 #define FREE1 A5 #define FREE2 A4 //Default Values for Ramping #define RAMPTIME 15 //in millisec #define RAMPSTEP 46 // ~1V/STEP depends on voltage in 12 bit (e.g. 2^12 = 4096, 4069/90V ~ 46/V) in Software ///How do i know Vmax and can calculate RAMPSTEP? //are set on Defaultvalues but shell editable from pc software //#define MAXVOLTAGE 80 // Global variables //Control Pins const unsigned char wr = 2; const unsigned char rd = 3; const unsigned char txe = 8; const unsigned char rxf = 9; //variables to save Data-Bytes in volatile unsigned char databus = 0x00; //temp. memory for Reading Databus interrupt unsigned char message[3]={0}; //array where the 3 Byte message is saved unsigned char messageindex = 0; //index of array unsigned char incommingByte = 0; //for incomming serial Data unsigned int recent_voltages[NUMCHANNELS] = {0}; //The actual Voltage of each channel is saved in this variable unsigned int set_voltage = 0; //The Value to which channel shell be set is saved in the variable unsigned int temp_voltage = 0; //temp. memory fot Value of Voltage boolean stat; //PLD Status-bit unsigned char wrapcounter = 0; //Wrap counter: unsigned char channel = 0; //channelnumber number unsigned char error = 0; //Errorcode from PLD unsigned char board = 0; //board number unsigned long loopstart = 0; unsigned long lastloop = 0; unsigned long loopduration = 0; //define Variables that mark edge-detection on RD and WR pin for Interrupt volatile boolean RisingEdge_RD = false; volatile boolean risingEdge_WR = false; //Type definitions typedef enum { set_message, send_message, get_message, //shell be defaultvalue, to await commands from PC pc_serial, parsing, } state_controler_t; //Type to define what microcontroller should do typedef enum { channel_status, sys_reset, global_set, channel_set, ramp_channel, ramp_global, idle //defaultvalue } function_t; //Type to define which function of PLD shell be build typedef enum { transmit_PLD_answer, get_request, transmit_channel_voltage, } communication_t; //Type to define communication with PC function_t function = idle; state_controler_t state_controler = pc_serial; communication_t pc_com = get_request; void setup() { //Initiate Controlpin Usage & Stati pinMode( wr, INPUT); pinMode( rd, INPUT); digitalWrite(txe, HIGH); pinMode( txe, OUTPUT); digitalWrite(rxf, HIGH); //set initial state of RXF# pinMode( rxf, OUTPUT); //Initiation of unused pins digitalWrite(FREE1, HIGH); pinMode(FREE1, OUTPUT); pinMode(FREE2, INPUT); //Set Databus to Input MakeDataBusInput(); // Binary: 00000000, since the bus is Bidirectional .. we better set to input in the idle case //set test_values /// can be erased when commuinication works //board = 0x09; //channel = 0x0f; //function = channel_set; //set_voltage = 0xaaa; digitalWrite(FREE1, LOW); //define Interrupts for RD and WR attachInterrupt(1, RisingEdgeOnRD, RISING); attachInterrupt(0, RisingEdgeOnWR, RISING); //Open comunication to PC Serial.begin(9600); //opens serial port, sets data rate to 9600 bps } void loop() { //calculate duration for last loop lastloop = loopstart; loopstart = micros(); loopduration = loopstart - lastloop; // Serial.print("Time: "); // Serial.print(loopduration); // Serial.println(" microseconds for loop"); // Communication with the PC, handle PC requests // Communication via USB if ( state_controler == pc_serial){ switch ( pc_com ){ //report PLD response to PC case transmit_PLD_answer: Serial.println("PLD answered: B"); for (messageindex = 0; messageindex < 3; messageindex++){ Serial.print(message[messageindex], BIN); Serial.print( "\t" ); } Serial.println(" in BIN "); for (messageindex = 0; messageindex < 3; messageindex++){ Serial.print(message[messageindex], HEX); Serial.print( "\t" ); } messageindex = 0; Serial.println(" in HEX "); Serial.println( "_______________________ " ); // if (function == channel_set){ // state_controler = set_message; // } pc_com = get_request; break; // Incoming Commands case get_request: while (Serial.available() < 3){}; if (Serial.available() > 0){ Serial.print("I received: "); messageindex = 0; while (messageindex < 3){ message[messageindex] = Serial.read(); Serial.print( "0x" ); Serial.print(message[messageindex], HEX); messageindex++; Serial.print( " " ); } messageindex = 0; //Serial.print(incommingByte, BYTE); Serial.println(",du Nase!"); } // if (function == ramp_channel){ // state_controler = set_message; // function = channel_set; // } state_controler = send_message; //function = channel_set break; // case transmit_channel_voltage: // Serial.println("Voltage of channel is: "); // for (messageindex = 0; messageindex < 3; messageindex++){ // Serial.print(recent_voltages[messageindex], BIN); // Serial.print( "\t" ); // } // break; } } //The following part sends the 3-Byte-Command to PLD //Build 3-Byte-Command that will be send to PLD PORTC ^= 1<> 4) ; } //Write Data from DATABUS void PutOnDataBus ( unsigned char data) { // okay .. .again // data0..3 is connected to PD4..7 // data4..7 is connected to PC0..3 PORTC = (PORTC & 0xf0) | (data&0xf0)>>4 ; PORTD = (PORTD & 0x0f) | (data&0x0f)<<4 ; } void MakeDataBusOutput() { // making the databus out can be done like this: // data0..3 is connected to PD4..7 // data4..7 is connected to PC0..3 // also auf PORTC die bits 0 bis 3 setzen! DDRC |= 0x0f; // und auf PORTD die bits 4 bis 7 setzen! DDRD |= 0xf0; // Um die Pullups muss man sicht nicht kümmern, da nach dieser Funktion sowieso ein neuer Wert auf den Bus // geschrieben wird. } void MakeDataBusInput() { // see the comments in MakeDataBusOutput() //first we switch the outs to ins // then we switch on the pullups DDRC &= 0xf0; DDRD &= 0x0f; } //System Reset void systemReset(){ for (messageindex = 0; messageindex < 2; messageindex++){ message[messageindex] = 0x0; // set alle 3byte to 0 } } //Read channel Status & Current void channelStaus(unsigned char brd, unsigned char chan){ message[0] = READSTATEBYTE | (brd << 1); //put funtion, board in first byte message[0] = message[0] | (chan >> 4); //add first channelbit to end of first byte message[1] = BLANKBYTE | (chan << 4); //put rest of channelbit in byte2 message[2] = BLANKBYTE; // set byte 3 to 0 } //Global set unsigned int globalSet(unsigned int volt){ message[0] = GLOBALSETBYTE; message[1] = BLANKBYTE | (volt >> 8); message[2] = BLANKBYTE | volt; return volt; } //Channel set to Voltage unsigned int channelSet(unsigned char brd, unsigned char chan, unsigned int volt){ message[0] = CHANNELSETBYTE | (brd << 1); message[0] = message[0] | (chan >> 4); message[1] = BLANKBYTE | (chan << 4); message[1] = message[1] | (volt >> 4); message[2] = BLANKBYTE | volt; return volt; } //functions for Interrupts on RD and WR void RisingEdgeOnRD(){ //digitalWrite(FREE1, HIGH); //digitalWrite(FREE1, LOW); PORTC ^= 1< 0) //ramp up { if (recent_voltages[RecentChannel(brd, chan)] + RAMPSTEP < volt){ volt = channelSet(brd, chan, (recent_voltages[RecentChannel(brd, chan)] + RAMPSTEP)); //ramps channel one Step to voltage and gives back voltagevalue function = ramp_channel; } else{ volt = channelSet(brd, chan, volt); //sets channel to chosen voltage ang gives back voltagevalue function = idle; //goes back to idle status that ramping is not recalled } } else if ((volt - recent_voltages[RecentChannel(brd, chan)]) < 0) //ramp down { if (recent_voltages[RecentChannel(brd, chan)] - RAMPSTEP > volt){ volt = channelSet(brd, chan, (recent_voltages[RecentChannel(brd, chan)] - RAMPSTEP)); //ramps channel one Step to voltage and gives back voltagevalue function = ramp_channel; } else{ volt = channelSet(brd, chan, volt); //sets channel to chosen voltage function = idle; //goes back to idle that ramping is not recalled } } else function = channel_status; //goes back to channel status that to tell status return volt; } unsigned int RampGlobal(unsigned int volt){ ///ich gehe zunächst mal davon aus, dass ich nur von Null rauf rampe // for (unsigned int channel = 0; channel <= NUMCHANNELS; channel++){ //check if evvery channel is set to 0 // if (recent_voltages != 0x0) return; //otherwise leave function // } if ((volt - recent_voltages[0]) > 0 && recent_voltages[0] + RAMPSTEP < volt){ ///wie bekomme ich die Spannungen der einzelnen Kanäle volt = globalSet(recent_voltages[0] + RAMPSTEP); //ramps all channels one Step to voltage and gives back voltagevalue function = ramp_global; } else if ((volt - recent_voltages[0]) > 0 && recent_voltages[0] + RAMPSTEP > volt){ volt = globalSet(volt); //sets channel to chosen voltage ang gives back voltagevalue function = idle; //goes back to idle status that ramping is not recalled } return volt; } /* void CommandToPLD(unsigned int txe, unsigned int rxf ){ //txe auf D8, rxf auf D9 if (txe == HIGH){ if (rxf == HIGH){ PORTB = B00000011; } else if(rxf == LOW){ PORTB = B00000001; } } else if (txe == PORTB = PORTB; } */