Index: fact/tools/hvMCUtest/fakePLD/fakePLD.pde
===================================================================
--- fact/tools/hvMCUtest/fakePLD/fakePLD.pde	(revision 12142)
+++ fact/tools/hvMCUtest/fakePLD/fakePLD.pde	(revision 12142)
@@ -0,0 +1,473 @@
+#include "macros.h"
+#include <avr/io.h>
+/*
+Mockup for the PLD of Volker Commichaus 
+Bias Crate Controller of the FACt Bias 
+voltage supply system
+
+Interface to FT245R or 
+something that behaves similarly:
+
+I am not going to use the Arduino specific digital input
+and digital output routines anymore . they are slow and stupid.
+But I like Serial.println very much.... so :-)
+
+
+
+Digital I/O:
+
+ATmega:	Net Name	:		Int/Out/Bi		: mnemonic
+---------------------------------------------------------------------
+PC0	:		RXF#		:		IN						:	Read from FIFO possible
+PC1	:		TXE#		:		IN						:	transmit enable
+PC2 :		RD#			:		OUT						:	Read from 'FIFO'
+PC3 :	  WR   		:		OUT						:	Write to 'FIFO'
+PC4 :	      		:		IN 						: HV down request button - low active
+PD2 :		D0			:		BI
+PD3	:		D1			:		BI
+PD4 :		D2			:		BI
+PD5	:		D3			:		BI
+PD6	:		D4			:		BI						:	Data
+PD7	:		D5			:		BI
+PB0	:		D6			:		BI
+PB1	:		D7			:		BI
+*/
+#define WR PC3
+#define RD PC2
+#define TXE PC1
+#define RXF PC0
+#define BUTTON PC4 
+/*
+-----------------------------------------------------------------------------
+
+Analog Inputs:
+
+This Software is intended to be run on an Arduino-like board.
+12 of the digi I/Os are used to communicate with the outside world,
+which is the FTDI245R in the first place.
+The FTDI245R interconnects this mockup via USB with a PC.
+This mockup will *not* provide any real functionality, as 
+the PLD in the CrateController does. It will just fake this 
+functionality. 
+So when it is ordered to set the voltage to e.g. 80V,
+it will store, that it was ordered so.
+If later it is asked to set the voltage to 10V, with a single 
+command, it will endure a fake 'trip'. 
+Everything, which happens, will be output via Serial Interface.
+
+It is not intended to input anything via the serial interface,
+since this is not possible in reality anyway.
+*/
+
+// comment this line out, if you want to skip the Serial 
+// Port entirely
+// #define SERIAL_ON
+
+#define DATABUSWIDTH 8
+#define MAXBOARDS 13
+#define EXISTINGBOARDS 10
+#define CHPERBOARD 32
+#define NUMCHANNELS EXISTINGBOARDS*CHPERBOARD
+
+#define BUTTON_PRESSED_BIT_POS 4
+#define DANGEROUSSTEP 200
+
+#define REFFGAPD 3 
+
+
+
+
+unsigned char message[3];
+unsigned char messageindex=0; 
+unsigned char answer[3];
+unsigned char answerindex=0; 
+
+unsigned char overcurrentbitmap[NUMCHANNELS/8 ];
+unsigned short voltages[NUMCHANNELS];
+unsigned short setvoltage =0;
+unsigned char statusbit =0;
+unsigned char w = 0;
+unsigned short current =0;
+unsigned char errorbits = 0;
+unsigned char board = 0;
+unsigned char channel = 0;
+
+unsigned char timeoutcounter =0;
+
+typedef enum {
+	state_receiving,
+	state_parsing,
+		state_system_reset,
+		state_read_status,
+		state_global_set,
+		state_set_voltage,
+	state_sending
+} state_t;
+
+  state_t last_state =  state_set_voltage;
+  state_t state =  state_receiving;
+	unsigned char command =0;
+
+
+void setup(){
+  
+	DDRC |= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+	#ifdef SERIAL_ON
+		Serial.begin(9600);
+	#endif	
+
+	// WR and RD are outputs
+	DDRC |= (1<<WR) | (1<<RD);
+	// WR idles low
+	PORTC &= ~1<<WR;
+	// RD idles high
+	PORTC |= (1<<RD);
+
+	// RXF, TXE and BUTTON are inputs
+	DDRC &= ~( (1<<TXE) | (1<<RXF) | (1<<BUTTON) );	
+  
+	// TXE and RXF should be held high by the FT245 or Arduino anyway, 
+	// but for convenience
+	// I pull them up, with ~20kohm reistors.
+
+	PORTC |= 1<<TXE;
+	PORTC |= 1<<RXF;
+
+	// The button should be low active.
+	// so I need a pull up here as well.
+	PORTC |= 1<< BUTTON;
+
+	// this affects PD2..PD7, PB0 and PB1.
+	//MakeDataBusInput ();
+	MAKEDATABUSINPUT;
+	
+	// for security, all unused pins I set to inputs, but 
+	// this might be anyway the atmega default case...
+	//DDRC &= ~( (1<<PC5) | (1<<PC6) | (1<<PC7) );	//arduino states: PC7 is not defined in this scope
+	DDRC &= ~( (1<<PC5) | (1<<PC6)  );	
+	DDRC |= 1<<PC5;
+	DDRB &= ~( (1<<PB2) | (1<<PB3) | (1<<PB4) );
+	
+	// to PB5 a LED is connected
+	DDRB |= 1<<PB5;
+	// this LED is high active ... I switch it on & off quickly
+	PORTB |= 1<<PB5;
+	delay (100);
+	PORTB &= ~(1<<PB5);
+
+	#ifdef SERIAL_ON
+	Serial.println("\n\nwelcome to the arduino FACT bias crate controller");
+	#endif
+
+	for (unsigned short channel = 0; channel < NUMCHANNELS; channel++)
+		voltages[channel] = 0;
+	for (unsigned short channel = 0; channel < NUMCHANNELS/8; channel++)
+		overcurrentbitmap[channel] = 0x00;
+	
+	/*
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+	delay (1000);
+*/
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+}
+
+void loop(){
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+
+	#ifdef SERIAL_ON  
+  if (state != last_state){
+  	Serial.print("state: ");
+		switch (state){
+			case state_receiving:
+  	    Serial.println("receiving");
+				break;
+	    case state_parsing:
+  	    Serial.println("parsing");
+				break;
+		  case state_system_reset:
+  	    Serial.println("sys reset");
+				break;
+		  case state_read_status:
+  	    Serial.println("read stat");
+				break;
+		  case state_global_set:
+  	    Serial.println("global set");
+				break;
+		  case state_set_voltage:
+  	    Serial.println("set volt");
+				break;
+	    case state_sending:
+  	    Serial.println("sending");
+				break;
+		}
+  }
+  last_state = state;
+	#endif
+
+switch( state ) {
+		case state_receiving:
+			//PORTB |= 1<<PB5;
+			//delay (100);
+			//PORTB &= ~(1<<PB5);
+     	// empfange bytes vom FT245 und 
+			// schreibe diese in ein byte-array der Länge 3
+			// wenn vollständig, dann gehe in zustand: state_parsing
+			if ( ISRXFLOW ){
+				// read one byte
+				CLRBIT(PORTC, RD);
+				message[messageindex]=READFROMDATABUS;
+				SETBIT(PORTC, RD); 
+				messageindex++;
+				while ( ISRXFLOW ){}
+			}
+			if (messageindex == 3) {
+				messageindex = 0;
+				state = state_parsing;
+			}
+			break;
+
+		case state_parsing:
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			#ifdef SERIAL_ON
+			for (int i=0; i<3; i++){
+				Serial.print(message[i], HEX);
+				if (i<2)
+					Serial.print(" ");
+				else
+					Serial.println("");
+			}
+			#endif
+			// schau in das 3-byte array und finde heraus, was zu tun ist.
+			// je nachdem was zu tun ist, wird die state variable anders gesetzt. 
+			// die message wird nicht verändert .. also die ersten bits nicht weggeschnitten oder so.
+			//
+			command = (message[0]) >> 5;
+			// das & 0x07 ist hier garnicht unbedingt notwendig, aber
+			// es stellt sicher, dass ich mit case 0 bis case 7 
+			// wirklich alle cases bearbeitet habe.. dann brauch
+			// ich keinen default case.
+			switch ( command & 0x07 ) {		 
+				case 0:
+					// System Reset
+					state = state_system_reset;
+					break;
+	
+				case 1:
+					// Read Channel Status & Current
+					state = state_read_status;
+					break;
+
+				case 2:
+					// Global Set
+					state = state_global_set;
+					break;
+	
+				case 3:
+					// Channel Set to voltage
+					state = state_set_voltage;
+					break;
+        
+        default:
+					// TODO Alarm, das ist unfug, aber nur zum testen
+					answer[0] = 0xff ;
+					answer[1] = 0x00 ;
+					answer[2] = 0xff ;
+				  state = state_sending;
+          break;
+				}
+				  //state = state_receiving;
+    break;
+
+ 		case state_system_reset:
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			w = (w+1)%8;
+			// Die message hat also den Befehl 'crate_reset' enthalten
+			// Also werde ich mal alles resetten, was ich so weiss 
+			// Ist aber wichtig, nochmal nach zu lesen, was eigentlich 
+			// wirklich resetted werden muss.
+			// 
+			// System reset setzt nicht die Spannungen auf null
+			// for (unsigned short channel = 0; channel < NUMCHANNELS; channel++)
+			// voltages[channel] = 0;
+			for (unsigned short channel = 0; channel < NUMCHANNELS/8; channel++)
+				overcurrentbitmap[channel] = 0x00;
+			answer[0] = w<<4;
+			answer[1] = 0x00;
+			answer[2] = 0x00;
+			state = state_sending;
+			break;
+
+		case state_read_status:
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			w = (w+1)%8;
+			// Hier hat der User, nach dem status eines bestimmten 
+			// boards und channels gefragt. Wo nach wurde gefragt?
+			board = (message[0] & 0x1e) >> 1;
+			channel = ((message[0] & 0x01) << 4) | ((message[1] & 0xf0) >> 4) ;
+			// Jetzt ist interessant, ob das angefragte board vorhanden ist
+			if (board < EXISTINGBOARDS){ // board exists
+				// we calculate the current I=U/R
+				current = voltages[board * CHPERBOARD + channel] / REFFGAPD;
+				answer[0] = (statusbit<<7) | (w<<4) | (unsigned char)((current>>8) & 0x000f);
+				answer[1] = (unsigned 	char)(current & 0x00ff);
+				answer[2] = (errorbits<<4) | (board&0x0f);
+			} else { // board is not exisiting
+				answer[0] = w<<4;
+				answer[1] = 0x00;
+				answer[2] = 0xf0 | (board&0x0f);
+			}
+			state = state_sending;
+			break;
+
+		
+		case state_set_voltage:
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			w = (w+1)%8;
+			board = (message[0] & 0x1e) >> 1;
+			channel = ((message[0] & 0x01) << 4) | ((message[1] & 0xf0) >> 4) ;
+			errorbits = 0;
+			statusbit = 0;
+	
+			errorbits |= ISBUTTONPRESSED<<(BUTTON_PRESSED_BIT_POS);
+			
+			if ( board < EXISTINGBOARDS){
+				setvoltage = ((unsigned short)*message+1) & 0x0fff;
+				if ( abs(voltages[board*CHPERBOARD + channel] - setvoltage) > DANGEROUSSTEP ) {// overcurrent!
+					overcurrentbitmap[board*CHPERBOARD/8+channel/8] |= 1<<channel%8;
+					statusbit = 1;
+				}
+				voltages[board*CHPERBOARD + channel] = setvoltage;
+				current = voltages[board * CHPERBOARD + channel] / REFFGAPD;
+			} else {
+				current = 0;
+				errorbits |= 0x07;
+			}
+
+
+			answer[0] =  statusbit<<7 | w<<4 | (unsigned char)((current>>8) & 0x000f);
+			answer[1] = (unsigned 	char)(current & 0x00ff);
+			answer[2] = errorbits<<4 | (board&0x0f);
+
+			state = state_sending;
+			break;
+
+		case state_global_set:
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			w = (w+1)%8;
+			// Erstmal schauen, was der user für eine Spannung setzen wollte
+			setvoltage = ((unsigned short)*message+1) & 0x0fff;
+			// so .. da jemand eine Spannung hoch oder runter setzt, könnte es sein
+			// dass ein überstrom zustand auftritt ... sagen wir mal, wenn die Spannung in einem 
+			// Schritt um mehr als 3 geändert wird, dann gibts nen Überstrom
+			// das ist eigentlich mist, aber ich will erstmal irgendwas hier einbauen.
+			for (unsigned char b=0; b < EXISTINGBOARDS; b++)
+				for (unsigned char c=0; c < CHPERBOARD; c++){
+					if ( abs(voltages[b*CHPERBOARD + c] - setvoltage) > DANGEROUSSTEP )// overcurrent!
+						overcurrentbitmap[b*CHPERBOARD/8+c/8] |= 1<<c%8;
+					voltages[b*CHPERBOARD + c] = setvoltage;
+				}
+			answer[0] = w<<4 ;
+			answer[1] = 0x00 ;
+			answer[2] = 0x00 ;
+			state = state_sending;
+			break;
+	
+		case state_sending:
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			PORTC ^= 1<<PC5;
+			// in diesem State bleibe ich solange es dauert, um die 'answer' 
+			// zu senden. Falls das senden aus irgendeinem Grund nicht gehen sollte
+			// bleibe ich *für immer* in diesem state.
+			if ( ISTXELOW ){
+				MAKEDATABUSOUTPUT;
+				PUTONDATABUS(answer[answerindex]);
+				SETBIT (PORTC, WR);
+				delayMicroseconds(6);
+				CLRBIT (PORTC, WR);
+				MAKEDATABUSINPUT;
+				
+				answerindex++;
+				//wait for txe going high
+				while ( ISTXELOW ){ }
+			} 
+				
+			if (answerindex == 3 || timeoutcounter >250) {
+				answerindex =0;
+				state = state_receiving;
+			}
+			break; 	
+			
+		default:
+				// ungültiger Zustand!
+        // Sollte eigentlich nie auftreten
+				// Wenn er auftritt, dann erzeuge ich eine Nachricht via 
+				// USB.
+			break;
+    }
+    
+}
+
Index: fact/tools/hvMCUtest/fakePLD/macros.h
===================================================================
--- fact/tools/hvMCUtest/fakePLD/macros.h	(revision 12142)
+++ fact/tools/hvMCUtest/fakePLD/macros.h	(revision 12142)
@@ -0,0 +1,15 @@
+
+#define SETBIT(PORT,PIN) (PORT |= 1<<PIN)
+#define CLRBIT(PORT,PIN) (PORT &= ~(1<<PIN))
+
+#define ISRXFHIGH ( PINC & (1<<RXF) )
+#define ISRXFLOW ( !ISRXFHIGH) 
+#define ISTXEHIGH ( PINC & (1<<TXE) ) 
+#define ISTXELOW ( !ISTXEHIGH) 
+#define READFROMDATABUS ( ( (PINB & 0x03) << 6 ) | ( (PIND & 0xfc) >> 2) )
+#define ISBUTTONPRESSED (!((PINC & (1<<BUTTON))>>BUTTON))
+
+#define MAKEDATABUSINPUT {DDRB &= ~((1 << 0) | (1<<1));  DDRD &= ~0xfc; PORTB |= (1 << 0) | (1<<1);  PORTD |= 0xfc; }
+#define MAKEDATABUSOUTPUT { DDRB |= (1 << 0) | (1<<1); DDRD |= 0xfc; }
+
+#define PUTONDATABUS(x) {PORTB = (PORTB & 0xfc) | (x&0xc0)>>6 ; PORTD = (PORTD & 0x03) | (x&0x3f)<<2;   }
