#include "macros.h" #include /* 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<> 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<> 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<> 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<>8) & 0x000f); answer[1] = (unsigned char)(current & 0x00ff); answer[2] = errorbits<<4 | (board&0x0f); state = state_sending; break; case state_global_set: PORTC ^= 1< DANGEROUSSTEP )// overcurrent! overcurrentbitmap[b*CHPERBOARD/8+c/8] |= 1<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; } }