source: fact/tools/hvMCUtest/ARDUINO_FTDI/ARDUINO_FTDI.pde@ 12224

Last change on this file since 12224 was 12224, checked in by Jens Buss, 13 years ago
Comments edited
File size: 17.7 KB
Line 
1/*
2Test Code to make Arduino Ethernet communicate with PLD of Volker Commichaus
3Bias Crate Controller of the FACt Bias voltage supply system
4instead of FT245R interface
5
6Interface to PLD or
7something that behaves similarly:
8
9Digital I/O:
10Arduino Pin : Net Name : Int/Out/Bi : mnemonic
11-----------------------------------------------------------------------------
12Pin D2 : WR : I : Write to 'FIFO'
13Pin D3 : RD# : I : Read from 'FIFO'
14Pin D8 : TXE# : O : transmit enable
15Pin D9 : RXF# : O : Read from FIFO possible
16Pin D4 : D0 : BI
17Pin D5 : D1 : BI
18Pin D6 : D2 : BI
19Pin D7 : D3 : BI
20Pin A0 : D4 : BI : Data
21Pin A1 : D5 : BI
22Pin A2 : D6 : BI
23Pin A3 : D7 : BI
24-----------------------------------------------------------------------------
25
26port definition:
27Port D consists of Arduino-Pins 0 - 7 and is used for Data exchange with the PLD
28Port C consists of Arduino-Pins A0 - A5 and is used for Data exchange with the PLD
29*/
30
31
32//define non transferable variables
33#define MAXBOARDS 13
34#define EXISTINGBOARDS 10
35#define CHPERBOARD 32
36#define NUMCHANNELS EXISTINGBOARDS*CHPERBOARD
37#define BLANKBYTE 0x00
38#define READSTATEBYTE 0x20
39#define GLOBALSETBYTE 0x40
40#define CHANNELSETBYTE 0x60
41#define FREE1 A5
42#define FREE2 A4
43
44//Default Values for Ramping
45#define RAMPTIME 15 //in millisec
46#define RAMPSTEP 46 // ~1V/STEP depends on voltage in 12 bit (e.g. 2^12 = 4096, 4069/90V ~ 46/V) in Software
47///How do i know Vmax and can calculate RAMPSTEP?
48//are set on Defaultvalues but shell editable from pc software
49
50
51//#define MAXVOLTAGE 80
52
53// Global variables
54 //Control Pins
55const unsigned char wr = 2;
56const unsigned char rd = 3;
57const unsigned char txe = 8;
58const unsigned char rxf = 9;
59
60 //variables to save Data-Bytes in
61volatile unsigned char databus = 0x00; //temp. memory for Reading Databus interrupt
62unsigned char message[3]={0}; //array where the 3 Byte message is saved
63unsigned char messageindex = 0; //index of array
64unsigned char incommingByte = 0; //for incomming serial Data
65unsigned int recent_voltages[NUMCHANNELS] = {0}; //The actual Voltage of each channel is saved in this variable
66unsigned int set_voltage = 0; //The Value to which channel shell be set is saved in the variable
67unsigned int temp_voltage = 0; //temp. memory fot Value of Voltage
68boolean stat; //PLD Status-bit
69unsigned char wrapcounter = 0; //Wrap counter:
70unsigned char channel = 0; //channelnumber number
71unsigned char error = 0; //Errorcode from PLD
72unsigned char board = 0; //board number
73unsigned long loopstart = 0;
74unsigned long lastloop = 0;
75unsigned long loopduration = 0;
76 //define Variables that mark edge-detection on RD and WR pin for Interrupt
77volatile boolean RisingEdge_RD = false;
78volatile boolean risingEdge_WR = false;
79
80//Type definitions
81typedef enum {
82 set_message,
83 send_message,
84 get_message, //shell be defaultvalue, to await commands from PC
85 pc_serial,
86 parsing,
87} state_controler_t; //Type to define what microcontroller should do
88
89
90typedef enum {
91 channel_status,
92 sys_reset,
93 global_set,
94 channel_set,
95 ramp_channel,
96 ramp_global,
97 idle //defaultvalue
98} function_t; //Type to define which function of PLD shell be build
99
100typedef enum {
101 transmit_PLD_answer,
102 get_request,
103 transmit_channel_voltage,
104} communication_t; //Type to define communication with PC
105
106function_t function = idle;
107state_controler_t state_controler = pc_serial;
108communication_t pc_com = get_request;
109
110
111void setup() {
112//Initiate Controlpin Usage & Stati
113 pinMode( wr, INPUT);
114 pinMode( rd, INPUT);
115 digitalWrite(txe, HIGH);
116 pinMode( txe, OUTPUT);
117 digitalWrite(rxf, HIGH); //set initial state of RXF#
118 pinMode( rxf, OUTPUT);
119//Initiation of unused pins
120 digitalWrite(FREE1, HIGH);
121 pinMode(FREE1, OUTPUT);
122 pinMode(FREE2, INPUT);
123
124//Set Databus to Input
125MakeDataBusInput(); // Binary: 00000000, since the bus is Bidirectional .. we better set to input in the idle case
126
127//set test_values
128/// can be erased when commuinication works
129//board = 0x09;
130//channel = 0x0f;
131//function = channel_set;
132//set_voltage = 0xaaa;
133digitalWrite(FREE1, LOW);
134
135//define Interrupts for RD and WR
136attachInterrupt(1, RisingEdgeOnRD, RISING);
137attachInterrupt(0, RisingEdgeOnWR, RISING);
138
139//Open comunication to PC
140Serial.begin(9600); //opens serial port, sets data rate to 9600 bps
141}
142
143
144void loop() {
145 //calculate duration for last loop
146 lastloop = loopstart;
147 loopstart = micros();
148 loopduration = loopstart - lastloop;
149// Serial.print("Time: ");
150// Serial.print(loopduration);
151// Serial.println(" microseconds for loop");
152
153 // Communication with the PC, handle PC requests
154 // Communication via USB
155 if ( state_controler == pc_serial){
156 switch ( pc_com ){
157 //report PLD response to PC
158 case transmit_PLD_answer:
159 Serial.println("PLD answered: B");
160 for (messageindex = 0; messageindex < 3; messageindex++){
161 Serial.print(message[messageindex], BIN);
162 Serial.print( "\t" );
163 }
164 Serial.println(" in BIN ");
165 for (messageindex = 0; messageindex < 3; messageindex++){
166 Serial.print(message[messageindex], HEX);
167 Serial.print( "\t" );
168 }
169 messageindex = 0;
170 Serial.println(" in HEX ");
171 Serial.println( "_______________________ " );
172// if (function == channel_set){
173// state_controler = set_message;
174// }
175 pc_com = get_request;
176 break;
177
178 // Incoming Commands
179 case get_request:
180 while (Serial.available() < 3){};
181 if (Serial.available() > 0){
182 Serial.print("I received: ");
183 messageindex = 0;
184 while (messageindex < 3){
185 message[messageindex] = Serial.read();
186 Serial.print( "0x" );
187 Serial.print(message[messageindex], HEX);
188 messageindex++;
189 Serial.print( " " );
190 }
191 messageindex = 0;
192 //Serial.print(incommingByte, BYTE);
193 Serial.println(",du Nase!");
194 }
195// if (function == ramp_channel){
196// state_controler = set_message;
197// function = channel_set;
198// }
199 state_controler = send_message;
200 //function = channel_set
201 break;
202
203// case transmit_channel_voltage:
204// Serial.println("Voltage of channel is: ");
205// for (messageindex = 0; messageindex < 3; messageindex++){
206// Serial.print(recent_voltages[messageindex], BIN);
207// Serial.print( "\t" );
208// }
209// break;
210 }
211 }
212
213//The following part sends the 3-Byte-Command to PLD
214 //Build 3-Byte-Command that will be send to PLD
215 PORTC ^= 1<<PC5; //Marker
216 PORTC ^= 1<<PC5; //Marker
217 if ( state_controler == set_message){
218 switch( function ){
219
220 case channel_status:
221 channelStaus(board, channel); //calls the channelstatus-function so values in message[] are set correctly
222 TransmitChannelVoltage(RecentChannel(board, channel));///verifizieren
223 break;
224
225 case sys_reset:
226 systemReset(); //calls the SystemReset-function so values in message[] are set correctly
227 break;
228
229 case global_set:
230 temp_voltage = RampGlobal(set_voltage); //calls the GlobalSet-function so values in message[] are set correctly //globalSet nicht mehr VOID
231 for (int x = 0; x <= NUMCHANNELS; x++){ ///verifizieren
232 recent_voltages[x] = temp_voltage;
233 }
234 TransmitChannelVoltage(0);///verifizieren
235 break;
236
237 case channel_set:
238 recent_voltages[RecentChannel(board, channel)] = RampChannel(board, channel, set_voltage); //calls the RampChannel-function so values in message[] are set correctly
239 // and saves the new Voltage in recent Voltage
240 if (recent_voltages[RecentChannel(board, channel)] == set_voltage){
241 function = idle;
242 }
243 break;
244
245 }
246 state_controler = send_message; //just for development
247 }
248 //Set 3-Byte-Command on DATABUS
249 //This is the FIFO Read Cycle, PLD reads from FIFO, ARDUINO writes to FIFO
250 if ( state_controler == send_message){
251 PORTC ^= 1<<PC5; //Marker
252 PORTC ^= 1<<PC5; //Marker
253 PORTC ^= 1<<PC5; //Marker
254 PORTC ^= 1<<PC5; //Marker
255 digitalWrite(txe, HIGH); //Forbid PLD to send Datan, needs 4 microsec
256 MakeDataBusOutput(); //set Databus as Output before you tell PLD that you have Data
257 //This is the Statemachine where the 3 bytes will be set on DATA Bus
258 switch( messageindex ){
259 case 0:
260 PutOnDataBus(message[messageindex]);
261 RisingEdge_RD = false;
262 digitalWrite(rxf, LOW ); //goes to low to tell PLD that Data is availiable, after PORTD to make shure that there is Data
263 while(!RisingEdge_RD){}
264 digitalWrite(rxf, HIGH );
265 messageindex++;
266 break;
267
268 case 1:
269 PutOnDataBus(message[messageindex]);
270 digitalWrite(rxf, LOW ); //goes to low to tell PLD that Data is availiable
271 while(!RisingEdge_RD){}
272 digitalWrite(rxf, HIGH );
273 messageindex++;
274 break;
275
276 case 2:
277 PutOnDataBus(message[messageindex]);
278 digitalWrite(rxf, LOW ); //goes to low to tell PLD that Data is availiable
279 while(!RisingEdge_RD ){}
280 digitalWrite(rxf, HIGH ); //goes to high to tell PLD that no Data is availiable
281 digitalWrite(txe, LOW ); //set TXE# to low to permit PLD to send DATA
282 MakeDataBusInput(); //Set PORT D to Input: PLD can write DATA on that Port
283 messageindex = 0;
284 state_controler = get_message; //Listen to PLD for status report
285 break;
286 }
287 RisingEdge_RD = false;
288 }
289
290//The following part gets the 3-Byte-Answer from PLD
291//The FIFO Write Cycle
292 if ( state_controler == get_message){
293 digitalWrite(rxf, HIGH ); //goes to high to tell PLD that no Data is availiable
294 MakeDataBusInput(); //set Port D as Input
295 digitalWrite(txe, LOW ); //goes to low to tell PLD it can send Data
296 if (risingEdge_WR){ //write Data from Byte into FiFo when WR goes from high to low and there was an Rising Edge before
297 switch( messageindex ){
298 case 0:
299 message[messageindex] = databus;
300 messageindex++;
301 break;
302
303 case 1:
304 message[messageindex] = databus;
305 messageindex++;
306 break;
307
308 case 2:
309 message[messageindex] = databus;
310 messageindex = 0;
311 state_controler = pc_serial;
312 pc_com = transmit_PLD_answer;
313 break;
314 }
315 risingEdge_WR = false; //reset RisingEdge interrupt variable to false to detect incomming Edge
316 digitalWrite(txe, HIGH); //reset TXE to tell PLD not not to write
317
318 }
319 }
320
321 // delay(1000); //slow down process for test pourpose
322}
323
324
325/*
326This are the funtions that can be used with the board:
327*/
328//Read Data from DATABUS
329unsigned char ReadFromDataBus(){
330 // The eight bits of the databus are distributed over
331 // the two differen ports of the ATmega. Port C and D
332 // actually they are connected like this:
333 // data0...data3 are connected to Arduino Pins D4..D7
334 // data4...data7 are connected to Arduino Pins C0..D3
335 return ( (PINC&0x0f) << 4 ) | ( (PIND&0xf0) >> 4) ;
336}
337
338//Write Data from DATABUS
339void PutOnDataBus ( unsigned char data) {
340 // okay .. .again
341 // data0..3 is connected to PD4..7
342 // data4..7 is connected to PC0..3
343 PORTC = (PORTC & 0xf0) | (data&0xf0)>>4 ;
344 PORTD = (PORTD & 0x0f) | (data&0x0f)<<4 ;
345
346}
347
348void MakeDataBusOutput() {
349 // making the databus out can be done like this:
350 // data0..3 is connected to PD4..7
351 // data4..7 is connected to PC0..3
352
353 // also auf PORTC die bits 0 bis 3 setzen!
354 DDRC |= 0x0f;
355 // und auf PORTD die bits 4 bis 7 setzen!
356 DDRD |= 0xf0;
357
358 // Um die Pullups muss man sicht nicht kümmern, da nach dieser Funktion sowieso ein neuer Wert auf den Bus
359 // geschrieben wird.
360}
361
362void MakeDataBusInput() {
363// see the comments in MakeDataBusOutput()
364
365//first we switch the outs to ins
366// then we switch on the pullups
367
368 DDRC &= 0xf0;
369 DDRD &= 0x0f;
370}
371
372//System Reset
373void systemReset(){
374 for (messageindex = 0; messageindex < 2; messageindex++){
375 message[messageindex] = 0x0; // set alle 3byte to 0
376 }
377}
378
379//Read channel Status & Current
380void channelStaus(unsigned char brd, unsigned char chan){
381 message[0] = READSTATEBYTE | (brd << 1); //put funtion, board in first byte
382 message[0] = message[0] | (chan >> 4); //add first channelbit to end of first byte
383 message[1] = BLANKBYTE | (chan << 4); //put rest of channelbit in byte2
384 message[2] = BLANKBYTE; // set byte 3 to 0
385}
386
387//Global set
388unsigned int globalSet(unsigned int volt){
389 message[0] = GLOBALSETBYTE;
390 message[1] = BLANKBYTE | (volt >> 8);
391 message[2] = BLANKBYTE | volt;
392 return volt;
393}
394
395//Channel set to Voltage
396unsigned int channelSet(unsigned char brd, unsigned char chan, unsigned int volt){
397 message[0] = CHANNELSETBYTE | (brd << 1);
398 message[0] = message[0] | (chan >> 4);
399 message[1] = BLANKBYTE | (chan << 4);
400 message[1] = message[1] | (volt >> 4);
401 message[2] = BLANKBYTE | volt;
402 return volt;
403}
404
405//functions for Interrupts on RD and WR
406void RisingEdgeOnRD(){
407 //digitalWrite(FREE1, HIGH);
408 //digitalWrite(FREE1, LOW);
409
410 PORTC ^= 1<<PC5;
411 PORTC ^= 1<<PC5;
412 PORTC ^= 1<<PC5;
413 PORTC ^= 1<<PC5;
414 PORTC ^= 1<<PC5;
415 PORTC ^= 1<<PC5;
416
417 RisingEdge_RD = true;
418}
419
420void RisingEdgeOnWR(){
421 databus = ReadFromDataBus();
422 risingEdge_WR = true;
423 PORTC ^= 1<<PC5;
424 PORTC ^= 1<<PC5;
425 PORTC ^= 1<<PC5;
426 PORTC ^= 1<<PC5;
427 PORTC ^= 1<<PC5;
428 PORTC ^= 1<<PC5;
429 PORTC ^= 1<<PC5;
430 PORTC ^= 1<<PC5;
431
432}
433
434void TransmitChannelVoltage(int chan){ ///verifizieren
435 Serial.println("Voltage of channel is: ");
436 Serial.print(recent_voltages[chan], HEX);
437 Serial.print( "in HEX \t" );
438}
439
440int RecentChannel(unsigned char board, unsigned char channel){ ///verifizieren
441return ((0x000f&board)<<5)|(0x1f&channel);
442}
443
444unsigned int RampChannel(unsigned char brd, unsigned char chan, unsigned int volt){ ///verifizieren
445 if ((volt - recent_voltages[RecentChannel(brd, chan)]) > 0) //ramp up
446 {
447 if (recent_voltages[RecentChannel(brd, chan)] + RAMPSTEP < volt){
448 volt = channelSet(brd, chan, (recent_voltages[RecentChannel(brd, chan)] + RAMPSTEP)); //ramps channel one Step to voltage and gives back voltagevalue
449 function = ramp_channel;
450 }
451 else{
452 volt = channelSet(brd, chan, volt); //sets channel to chosen voltage ang gives back voltagevalue
453 function = idle; //goes back to idle status that ramping is not recalled
454 }
455 }
456 else if ((volt - recent_voltages[RecentChannel(brd, chan)]) < 0) //ramp down
457 {
458 if (recent_voltages[RecentChannel(brd, chan)] - RAMPSTEP > volt){
459 volt = channelSet(brd, chan, (recent_voltages[RecentChannel(brd, chan)] - RAMPSTEP)); //ramps channel one Step to voltage and gives back voltagevalue
460 function = ramp_channel;
461 }
462 else{
463 volt = channelSet(brd, chan, volt); //sets channel to chosen voltage
464 function = idle; //goes back to idle that ramping is not recalled
465 }
466 }
467 else function = channel_status; //goes back to channel status that to tell status
468 return volt;
469}
470
471unsigned int RampGlobal(unsigned int volt){ ///ich gehe zunächst mal davon aus, dass ich nur von Null rauf rampe
472// for (unsigned int channel = 0; channel <= NUMCHANNELS; channel++){ //check if evvery channel is set to 0
473// if (recent_voltages != 0x0) return; //otherwise leave function
474// }
475 if ((volt - recent_voltages[0]) > 0 && recent_voltages[0] + RAMPSTEP < volt){ ///wie bekomme ich die Spannungen der einzelnen Kanäle
476 volt = globalSet(recent_voltages[0] + RAMPSTEP); //ramps all channels one Step to voltage and gives back voltagevalue
477 function = ramp_global;
478 }
479 else if ((volt - recent_voltages[0]) > 0 && recent_voltages[0] + RAMPSTEP > volt){
480 volt = globalSet(volt); //sets channel to chosen voltage ang gives back voltagevalue
481 function = idle; //goes back to idle status that ramping is not recalled
482 }
483 return volt;
484}
485
486
487/*
488void CommandToPLD(unsigned int txe, unsigned int rxf ){
489//txe auf D8, rxf auf D9
490if (txe == HIGH){
491 if (rxf == HIGH){
492 PORTB = B00000011;
493 }
494 else if(rxf == LOW){
495 PORTB = B00000001;
496 }
497}
498else if (txe ==
499PORTB = PORTB;
500}
501*/
Note: See TracBrowser for help on using the repository browser.