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

Last change on this file since 12386 was 12225, checked in by Jens Buss, 13 years ago
more comments edited
File size: 17.6 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}
322
323
324/*
325This are the funtions that can be used with the board:
326*/
327//Read Data from DATABUS
328unsigned char ReadFromDataBus(){
329 // The eight bits of the databus are distributed over
330 // the two differen ports of the ATmega. Port C and D
331 // actually they are connected like this:
332 // data0...data3 are connected to Arduino Pins D4..D7
333 // data4...data7 are connected to Arduino Pins C0..D3
334 return ( (PINC&0x0f) << 4 ) | ( (PIND&0xf0) >> 4) ;
335}
336
337//Write Data from DATABUS
338void PutOnDataBus ( unsigned char data) {
339 // okay .. .again
340 // data0..3 is connected to PD4..7
341 // data4..7 is connected to PC0..3
342 PORTC = (PORTC & 0xf0) | (data&0xf0)>>4 ;
343 PORTD = (PORTD & 0x0f) | (data&0x0f)<<4 ;
344
345}
346
347void MakeDataBusOutput() {
348 // making the databus out can be done like this:
349 // data0..3 is connected to PD4..7
350 // data4..7 is connected to PC0..3
351
352 // also auf PORTC die bits 0 bis 3 setzen!
353 DDRC |= 0x0f;
354 // und auf PORTD die bits 4 bis 7 setzen!
355 DDRD |= 0xf0;
356
357 // Um die Pullups muss man sicht nicht kümmern, da nach dieser Funktion sowieso ein neuer Wert auf den Bus
358 // geschrieben wird.
359}
360
361void MakeDataBusInput() {
362// see the comments in MakeDataBusOutput()
363
364//first we switch the outs to ins
365// then we switch on the pullups
366
367 DDRC &= 0xf0;
368 DDRD &= 0x0f;
369}
370
371//System Reset
372void systemReset(){
373 for (messageindex = 0; messageindex < 2; messageindex++){
374 message[messageindex] = 0x0; // set alle 3byte to 0
375 }
376}
377
378//Read channel Status & Current
379void channelStaus(unsigned char brd, unsigned char chan){
380 message[0] = READSTATEBYTE | (brd << 1); //put funtion, board in first byte
381 message[0] = message[0] | (chan >> 4); //add first channelbit to end of first byte
382 message[1] = BLANKBYTE | (chan << 4); //put rest of channelbit in byte2
383 message[2] = BLANKBYTE; // set byte 3 to 0
384}
385
386//Global set
387unsigned int globalSet(unsigned int volt){
388 message[0] = GLOBALSETBYTE;
389 message[1] = BLANKBYTE | (volt >> 8);
390 message[2] = BLANKBYTE | volt;
391 return volt;
392}
393
394//Channel set to Voltage
395unsigned int channelSet(unsigned char brd, unsigned char chan, unsigned int volt){
396 message[0] = CHANNELSETBYTE | (brd << 1);
397 message[0] = message[0] | (chan >> 4);
398 message[1] = BLANKBYTE | (chan << 4);
399 message[1] = message[1] | (volt >> 4);
400 message[2] = BLANKBYTE | volt;
401 return volt;
402}
403
404//functions for Interrupts on RD and WR
405void RisingEdgeOnRD(){
406 //digitalWrite(FREE1, HIGH);
407 //digitalWrite(FREE1, LOW);
408
409 PORTC ^= 1<<PC5;
410 PORTC ^= 1<<PC5;
411 PORTC ^= 1<<PC5;
412 PORTC ^= 1<<PC5;
413 PORTC ^= 1<<PC5;
414 PORTC ^= 1<<PC5;
415
416 RisingEdge_RD = true;
417}
418
419void RisingEdgeOnWR(){
420 databus = ReadFromDataBus();
421 risingEdge_WR = true;
422 PORTC ^= 1<<PC5;
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
431}
432
433void TransmitChannelVoltage(int chan){ ///verifizieren
434 Serial.println("Voltage of channel is: ");
435 Serial.print(recent_voltages[chan], HEX);
436 Serial.print( "in HEX \t" );
437}
438
439int RecentChannel(unsigned char board, unsigned char channel){ ///verifizieren
440return ((0x000f&board)<<5)|(0x1f&channel);
441}
442
443unsigned int RampChannel(unsigned char brd, unsigned char chan, unsigned int volt){ ///verifizieren
444 if ((volt - recent_voltages[RecentChannel(brd, chan)]) > 0) //ramp up
445 {
446 if (recent_voltages[RecentChannel(brd, chan)] + RAMPSTEP < volt){
447 volt = channelSet(brd, chan, (recent_voltages[RecentChannel(brd, chan)] + RAMPSTEP)); //ramps channel one Step to voltage and gives back voltagevalue
448 function = ramp_channel;
449 }
450 else{
451 volt = channelSet(brd, chan, volt); //sets channel to chosen voltage ang gives back voltagevalue
452 function = idle; //goes back to idle status that ramping is not recalled
453 }
454 }
455 else if ((volt - recent_voltages[RecentChannel(brd, chan)]) < 0) //ramp down
456 {
457 if (recent_voltages[RecentChannel(brd, chan)] - RAMPSTEP > volt){
458 volt = channelSet(brd, chan, (recent_voltages[RecentChannel(brd, chan)] - RAMPSTEP)); //ramps channel one Step to voltage and gives back voltagevalue
459 function = ramp_channel;
460 }
461 else{
462 volt = channelSet(brd, chan, volt); //sets channel to chosen voltage
463 function = idle; //goes back to idle that ramping is not recalled
464 }
465 }
466 else function = channel_status; //goes back to channel status that to tell status
467 return volt;
468}
469
470unsigned int RampGlobal(unsigned int volt){ ///ich gehe zunächst mal davon aus, dass ich nur von Null rauf rampe
471// for (unsigned int channel = 0; channel <= NUMCHANNELS; channel++){ //check if evvery channel is set to 0
472// if (recent_voltages != 0x0) return; //otherwise leave function
473// }
474 if ((volt - recent_voltages[0]) > 0 && recent_voltages[0] + RAMPSTEP < volt){ ///wie bekomme ich die Spannungen der einzelnen Kanäle
475 volt = globalSet(recent_voltages[0] + RAMPSTEP); //ramps all channels one Step to voltage and gives back voltagevalue
476 function = ramp_global;
477 }
478 else if ((volt - recent_voltages[0]) > 0 && recent_voltages[0] + RAMPSTEP > volt){
479 volt = globalSet(volt); //sets channel to chosen voltage ang gives back voltagevalue
480 function = idle; //goes back to idle status that ramping is not recalled
481 }
482 return volt;
483}
484
485
486/*
487void CommandToPLD(unsigned int txe, unsigned int rxf ){
488//txe auf D8, rxf auf D9
489if (txe == HIGH){
490 if (rxf == HIGH){
491 PORTB = B00000011;
492 }
493 else if(rxf == LOW){
494 PORTB = B00000001;
495 }
496}
497else if (txe ==
498PORTB = PORTB;
499}
500*/
Note: See TracBrowser for help on using the repository browser.