← Back to dashboard

File view

plc_outputs.lib

1
//$Id: ism_outputs.lib,v 1.3 2008-07-28 19:18:59 charlie Exp $
2
/*
3
   $Log: ism_outputs.lib,v $
4
5
6
7
*/
8
9
/*** BeginHeader */
10
11
#ifndef	__ISM_OUTPUTS_
12
#define	__ISM_OUTPUTS_
13
14
/*** EndHeader */
15
16
/*** BeginHeader
17
18
InitializeOutputs
19
WriteOutputs
20
21
*/
22
23
//Define constants for ssr drivers ******************************************************
24
25
#define  OUTPUT0_WR_BIT 0
26
#define  OUTPUT1_WR_BIT 0
27
28
//Function prototypes *******************************************************************
29
30
nodebug void  InitializeOutputs ();						//initialize port to write leds
31
nodebug void  WrOutputs (int);
32
nodebug void  setOutput(int bit, int value);
33
		  void  WriteOutputs();
34
nodebug int   testOutput(int bit);
35
		  int   ShuntValveDutyCycle (int ctlword, int * noRead, int ResilVal);
36
37
38
/*** EndHeader */
39
40
//Initialize ports used by ssr handler **************************************************
41
42
void InitializeOutputs ()
43
{
44
	int i;
45
	Ms start;
46
	printf("Init Outputs ...\n");
47
	//ibRegister arguments come from plc_constants.lib
48
	WrPortI (IbRegister (OUTPUT0_WR_BIT), NULL, (ONE_WAIT | WRITE_STROBE | PERMIT_WRITE));
49
	BitWrPortI (PEFR, &PEFRShadow, 1, OUTPUT0_WR_BIT);
50
	BitWrPortI (PEDDR, &PEDDRShadow, 1, OUTPUT0_WR_BIT);
51
52
	WrPortI (IbRegister (OUTPUT1_WR_BIT), NULL, (ONE_WAIT | WRITE_STROBE | PERMIT_WRITE));
53
	BitWrPortI (PEFR, &PEFRShadow, 1, OUTPUT1_WR_BIT);
54
	BitWrPortI (PEDDR, &PEDDRShadow, 1, OUTPUT1_WR_BIT);
55
56
   outputWord = 0;
57
58
	WrOutputs(~0);
59
}
60
61
// WriteOutputs ***************************************************************************
62
63
void WriteOutputs ()
64
{
65
	int i;
66
   int j;
67
	int result;
68
   int sumpResult;
69
   int presResult;
70
   int shuntResult;
71
   int alarmOutPos;
72
   int *ACInputs;
73
74
   if (Config.SiteConfigFlag)
75
   {
76
77
  result = 0;
78
  ACInputs = GetACInputArray();
79
  outputWord = 0;
80
81
	for (i = 0 ; i < Config.N_Turbines ; i++)
82
	{
83
	   if (Channel[i].Turbine || Channel[i].OverRideFlag)
84
	   	setOutput(Channel[i].IOChannel,ON);
85
	   else
86
	   	setOutput(Channel[i].IOChannel,OFF);
87
	   if (Channel[i].State == 6 || Channel[i].PresAlmFlag)
88
	   	result = 1;
89
	}
90
91
	// CV output and timer control
92
93
	for (i = 0 ; i < Config.N_Products ; i++)
94
	{
95
  		if (Product[i].Authorize || Channel[Product[i].LeadTurbine].Turbine)
96
      {
97
      	if (Product[i].CV.firstAuthFlag)
98
         {
99
            Product[i].CV.firstAuthFlag = 0;
100
         	Product[i].CV.authStart = SEC_TIMER;
101
         }
102
         for (j = 0 ; j < Product[i].CV.SCV ; j++)
103
         {
104
         	if (Product[i].CV.scvOnDly * (j+1) + Product[i].CV.authStart <= SEC_TIMER)
105
	         {
106
	            setOutput(Product[i].CV.scvIOChannel + j,ON);
107
	         }
108
         }
109
         for (j = 0 ; j < Product[i].CV.PCV ; j++)
110
         {
111
	         if (Channel[Product[i].LeadTurbine].RdyFlag &&
112
	             Product[i].CV.pcvOnDly * (j+1) + Product[i].CV.authStart <= SEC_TIMER
113
                && (Channel[Product[i].LeadTurbine].PresFlag || Product[i].CV.CVLock))
114
	         {
115
               setOutput(Product[i].CV.pcvIOChannel + j,ON);
116
               Product[i].CV.CVLock = ON;
117
	         }
118
         }
119
         for (j = 0 ; j < Product[i].CV.DCV ; j++)
120
         {
121
	         if (Channel[Product[i].LeadTurbine].RdyFlag &&
122
	             Product[i].CV.dcvOnDly + Product[i].CV.authStart <= SEC_TIMER
123
                && (Channel[Product[i].LeadTurbine].PresFlag || Product[i].CV.CVLock))
124
	         {
125
               if (ACInputs[Product[i].FirstTurbine + j]  != 0)
126
               {
127
               	Product[i].CV.CVLock = ON;
128
               	setOutput(Product[i].CV.dcvIOChannel + j,ON);
129
               }
130
               else
131
                  setOutput(Product[i].CV.dcvIOChannel + j,OFF);
132
	         }
133
         }
134
      }
135
      else
136
      {
137
      	if (!Product[i].CV.firstAuthFlag)
138
         {
139
            Product[i].CV.firstAuthFlag = 1;
140
         	Product[i].CV.authStart = SEC_TIMER;
141
         }
142
      	for (j = 0 ; j < Product[i].CV.SCV ; j++)
143
         {
144
         	if (Product[i].CV.scvOffDly * (j+1) + Product[i].CV.authStart <= SEC_TIMER)
145
	         {
146
	            setOutput(Product[i].CV.scvIOChannel + j,OFF);
147
	         }
148
         }
149
         for (j = 0 ; j < Product[i].CV.PCV ; j++)
150
         {
151
         	if (Product[i].CV.pcvOffDly * (j+1) + Product[i].CV.authStart <= SEC_TIMER)
152
	         {
153
               setOutput(Product[i].CV.pcvIOChannel + j,OFF);
154
               Product[i].CV.CVLock = OFF;
155
	         }
156
         }
157
         for (j = 0 ; j < Product[i].CV.DCV ; j++)
158
         {
159
         	if (Product[i].CV.dcvOffDly + Product[i].CV.authStart <= SEC_TIMER)
160
	         {
161
	             setOutput(Product[i].CV.dcvIOChannel + j,OFF);
162
                Product[i].CV.CVLock = OFF;
163
	         }
164
         }
165
      }
166
   }
167
	#if SCH2
168
169
      if (Product[0].ReturnFuel)
170
      	setOutput(3,ON);
171
      else
172
      {
173
      	if (Product[0].CheckPres)
174
      		setOutput(2,ON);
175
      	else
176
      		setOutput(2,OFF);
177
      	setOutput(3,OFF);
178
      }
179
	#endif
180
181
  #if MODBUS_S_ON
182
183
      // Define all outputs to product 1
184
      SetStatusReg(TURBINE_OUT, 0, 0, outputWord & 0x000F);    // Write outputs 1-4
185
      SetStatusReg(CV_OUT, 0, 0, outputWord & 0x00F0);         // Write outputs 5-8
186
187
      // Need to define outputs to each product
188
189
      #if SCH2
190
         SetStatusReg(TURBINE_OUT, 0, 0, outputWord & 0x000B);		// Write outputs 1,2
191
      	SetStatusReg(CV_OUT, 0, 0, outputWord & 0x0034);         // Write Outputs 3, 5, 6
192
      #endif
193
194
   #endif
195
196
         sumpResult = 0;
197
			presResult = 0;
198
         
199
         #if MODBUS_M_ON == 0
200
         	alarmOutPos = N_OUTPUTS - Config.N_PS - 1;
201
         	for (i = 0 ; i < Config.N_Turbines ; i++)
202
            {
203
               if (Channel[i].LeadFlag)
204
               {
205
                  setOutput(N_OUTPUTS - Channel[i].IOPS -1 ,
206
                  	ShuntValveDutyCycle (Channel[i].ShuntValve, &Channel[i].NoReadIS, Channel[i].ResilVal));
207
                  #if MODBUS_S_ON
208
      					SetStatusReg(SHUNT_VALVE_1+i,Channel[i].ShuntValve);
209
                  #endif
210
               }
211
            }
212
	         for (i = 0 ; i < Config.N_Products ; i++)
213
	         {
214
            	sumpResult = 0;
215
	            for (j = Product[i].FirstTurbine ; j < Product[i].FirstTurbine + Product[i].N_Turbines ; j++)
216
	            {
217
	               if (Channel[j].AlarmFlag != NO_ALARM)
218
	                  sumpResult = 1;
219
	            }
220
               if (
221
               setOutput(alarmOutPos - Config.N_Products + 1 + i, sumpResult);
222
	         }
223
         #endif
224
225
         #if MODBUS_M_ON
226
         	result = 0;
227
            alarmOutPos = CV_OFFSET + Config.N_CVs;
228
            #if SCH2
229
            	alarmOutPos++;
230
            #endif
231
            //alarmOutPos = N_OUTPUTS - 1;
232
            #if ALARM_PER_PROD
233
               for (i = 0 ; i < Config.N_Products ; i++)
234
               {
235
                  sumpResult = 0;
236
                  for (j = Product[i].FirstTurbine ; j < Product[i].FirstTurbine + Product[i].N_Turbines ; j++)
237
                  {
238
                     if (Channel[j].AlarmFlag != NO_ALARM || (Channel[j].SensorOutFlag && Channel[j].State != 3))
239
                        sumpResult |= 1;
240
                  }
241
                  // Test if enough alarm outputs
242
                  if (N_OUTPUTS - Config.N_Products >= alarmOutPos)
243
                  {
244
                  	//setOutput(alarmOutPos - Config.N_Products + 1 + i, sumpResult);
245
                     setOutput(alarmOutPos + i, sumpResult);
246
                     #if WILDCO      									// For Permit Output
247
                     	if ((Channel[Product[i].LeadTurbine].AlarmFlag > NO_ALARM &&
248
                        	  Channel[Product[i].LeadTurbine].AlarmFlag < NO_WARNING) ||
249
                            (Channel[Product[i].LeadTurbine].SensorOutFlag &&
250
                             Channel[Product[i].LeadTurbine].State != 3))
251
                        	setOutput(alarmOutPos + i + 1, 1);
252
                        else
253
                        	setOutput(alarmOutPos + i + 1, 0);
254
               		#endif
255
                  }
256
                  else
257
                  	result |= sumpResult;
258
               }
259
               // If at least 1 free alarm output
260
               if (N_OUTPUTS - Config.N_Products < alarmOutPos && N_OUTPUTS > alarmOutPos)
261
               	setOutput(N_OUTPUTS - 1, result);
262
            #else
263
            	for (i = 0 ; i < Config.N_Turbines ; i++)
264
               {
265
	               sumpResult = 0;
266
                  if (Channel[i].AlarmFlag != NO_ALARM || (Channel[j].SensorOutFlag && Channel[j].State != 3))
267
                     sumpResult = 1;
268
               	setOutput(alarmOutPos + i, sumpResult);
269
               }
270
            #endif
271
         #endif
272
273
   
274
275
		WrOutputs(~outputWord);
276
	}
277
278
279
}
280
281
//Write output status to ssrs ***********************************************************
282
283
void	WrOutputs (int value)
284
{
285
	int flip;
286
	int i;
287
	flip = 0;
288
	for (i = 0 ; i < N_OUTPUTS ; i++)
289
	{
290
		flip |= ((value >> (N_OUTPUTS-1-i)) & 1) << i;
291
	}
292
	//ExternalAddress arguments come from FCH_CONSTANTS.LIB
293
   #if BOARDREV == 'C'
294
      WrPortE (ExternalAddress(OUTPUT0_WR_BIT), NULL, value & 0xff);
295
   #else
296
		WrPortE (ExternalAddress(OUTPUT0_WR_BIT), NULL, flip & 0xff);
297
		WrPortE (ExternalAddress(OUTPUT1_WR_BIT), NULL, (flip >> 8) & 0xff);
298
   #endif
299
}
300
301
// SetOutput ****************************************************************************
302
303
void setOutput(int bit, int value)
304
{
305
	if (value)
306
		outputWord |= BitToMask(bit);
307
  else
308
		outputWord &= ~BitToMask(bit);
309
}
310
311
// TestOutput ***************************************************************************
312
313
int testOutput(int bit)
314
{
315
	int result;
316
	result = outputWord & BitToMask(bit);
317
	return result;
318
}
319
320
// Shunt Valve Duty Cyle ******************************************************
321
322
int  ShuntValveDutyCycle (int ctlword, int * noRead, int ResilVal)
323
{
324
	#define MIN_ON_CYCLE 50
325
   #define MAX_ON_CYCLE 1000
326
   #define MIN_CYCLE		1000
327
   #define MAX_CYCLE		2000
328
   #define RES_MULTI    2
329
   #define REST_PERIOD  5
330
331
   int onCycle;
332
   int totalCycle;
333
   int result;
334
   int noReadCycle;
335
336
   result = 0;
337
338
   onCycle = ResilVal * RES_MULTI;
339
   if (onCycle <= MIN_ON_CYCLE)
340
   	onCycle = MIN_ON_CYCLE;
341
   else if (onCycle >= MAX_ON_CYCLE)
342
   	onCycle = MAX_ON_CYCLE;
343
344
   if (onCycle < MIN_CYCLE / 2)
345
   	totalCycle = MIN_CYCLE;
346
   else
347
      totalCycle = MAX_CYCLE;
348
349
   noReadCycle = onCycle * REST_PERIOD;
350
   if (noReadCycle >= totalCycle)
351
   	noReadCycle = totalCycle - 100;
352
353
   if (ctlword == ON)
354
   {
355
      if ((MS_TIMER % totalCycle) <= onCycle)
356
      {
357
         result = ON;
358
         *noRead = ON;
359
      }
360
      else
361
      {
362
         result = OFF;
363
         if ((MS_TIMER % totalCycle) <= noReadCycle)
364
         	*noRead = ON;
365
         else
366
         	*noRead = OFF;
367
      }
368
   }
369
   else
370
   {
371
		result = OFF;
372
   	*noRead = OFF;
373
   }
374
375
   return result;
376
}
377
378
//End of ssr handler ********************************************************************
379
380
/*** BeginHeader */
381
382
#endif
383
384
/*** EndHeader */