← Back to dashboard

File view

BAS_MODBUS_SLAVE.LIB

1
/*
2
***** Comm Port Pin Out *****
3
4
   SATA  			   DB-9
5
6
7	GND				9
7
6	RS485 A 			8	RS232 CTS
8
5	RS485 B 			7
9
4	RS232 CTS   	6	RS485 B
10
3	RS232 RX  		5	GND
11
2	RS232 TX 		4
12
1	GND          	3  RS232 TX
13
						2  RS232 RX
14
                  1	RS485 A
15
*/
16
17
/*** BeginHeader
18
*/
19
#ifndef _BAS_MODBUS_SLAVE_
20
#define _BAS_MODBUS_SLAVE_
21
22
23
#define MODBUS_DEBUG debug
24
#define MODBUS_SLAVE_DEBUG debug
25
//#define MODBUS_DEBUG_PRINT debug
26
#define USE_MODBUS_CRC
27
#define MB_SLAVE_485 0
28
29
#define MB_GROUP_STATUS		0
30
#define MB_GROUP_ALARM  	100
31
#define MB_GROUP_CONFIG 	200
32
#define MB_GROUP_CONTROL 	300
33
34
// Controller Status List
35
enum
36
{
37
AUTH_INPUTS,
38
TURBINE_OUT,
39
CV_OUT,
40
SUMP_SENSOR,
41
SHUNT_VALVE,
42
FLOW_SWITCH,
43
PROD_PRES,
44
PLC_STATE,
45
GPH3_PASSED,
46
PASSED_02,
47
PASSED_01,
48
CURRENT_TESTS,
49
CURRENT_LRS,
50
DT_LEVEL_TC,
51
DT_LEVEL_TC_PRECISION,
52
DT_LEVEL_ACTUAL,
53
DT_LEVEL_DIRECTION,
54
DT_VOLUME_TC,
55
DT_VOLUME_TC_PRECISION,
56
DT_VOLUME_RATE,
57
DT_VOLUME_ACTUAL,
58
DT_ULLAGE,
59
FUEL_TEMPS,
60
FILTER_ACTIVE,
61
MOTORIZED_CV_LS_13,
62
MOTORIZED_CV_LS_16,
63
MOTORIZED_CV_LS_17,
64
BOILER_DISABLE,
65
STATUS_LEN
66
};
67
68
// Alarm List
69
enum
70
{
71
PRES_ALARMS,
72
GPH3FAILURES,
73
SENSOR_OUTS,
74
PRECISION_TEST_FAILURES,
75
LRS,
76
NO_FLOW_AL,
77
DEAD_TURBINE,
78
POWER_FAILURE,
79
RESERVED_ALARM_01,
80
RESERVED_ALARM_02,
81
FAILED_TURBINE_CV_WARNING,
82
GPH3FAILURES_WARNING,
83
SYSTEM_NOT_CONFIG,
84
RESERVED_WARNING_02,
85
DT_NO_FUEL,
86
DT_LOW_FUEL,
87
DT_OVERFILL,
88
ALARM_LEN
89
};
90
91
// Controller Config List
92
enum
93
{
94
UNKNOWN_LIST_1,
95
UNKNOWN_LIST_2,
96
UNKNOWN_LIST_3,
97
CONFIG_WRITE_CONFIRM,
98
CONTROL_CONFIG_LEN
99
};
100
101
// Control Commands
102
enum
103
{
104
AUTH_REQUESTS,
105
RESET_ALL_CHANNELS,
106
RESET_CHANNEL,
107
PRECISION_TEST_01,
108
PRECISION_TEST_02,
109
PRECISION_TEST_ABORT,
110
TURN_ON_OUTPUTS,
111
TURN_OFF_OUTPUTS,
112
DT_LEVEL_RAISE,
113
DT_LEVEL_LOWER,
114
DT_TOP_OFF,
115
ESTOP,
116
RESERVED_WRITE_2S,
117
RESERVED_WRITE_3S,
118
RESERVED_WRITE_4S,
119
CTL_WRITE_CONFIRM,
120
CONTROL_COMMAND_LEN
121
};
122
123
int BAS_SLAVE_Init();
124
125
/*** EndHeader */
126
/*** BeginHeader MODBUS_Serial_Init */
127
#define BINBUFSIZE 			127
128
#define BOUTBUFSIZE 			127
129
#define DINBUFSIZE			127
130
#define DOUTBUFSIZE			127
131
#define RS485_TX_ENABLE_BIT 2
132
#define MODBUS_COMM_TO		60
133
extern int Serial_timeout;
134
int MODBUS_Serial_Init(void);
135
#if MB_SLAVE_485
136
	void ser485Tx(void);
137
	void ser485Rx(void);
138
#endif
139
void 			 SetStatusReg(int idx, int prod, int ch, int val);
140
unsigned int GetStatusReg(int idx, int prod);
141
void 			 SetAlarmReg(int idx, int prod, int ch, int val);
142
unsigned int GetAlarmReg(int idx, int prod);
143
void 			 SetConfigReg(int idx, int prod, int val);
144
unsigned int GetConfigReg(int idx, int prod);
145
void 			 SetRdControlReg(int idx, int prod, int val);
146
unsigned int GetRdControlReg(int idx, int prod);
147
void 			 SetWrControlReg(int idx, int prod, int val);
148
unsigned int GetWrControlReg(int idx, int prod);
149
150
/*** EndHeader */
151
/*** BeginHeader
152
BAS_SLAVE_Init
153
SetStatusReg
154
GetStatusReg
155
SetAlarmReg
156
GetAlarmReg
157
SetConfigReg
158
GetConfigReg
159
SetWrControlReg
160
GetWrControlReg
161
*/
162
163
/*** EndHeader */
164
165
//*******************************************************************************************
166
167
int MBS_Serial_timeout;
168
unsigned int readOnlyStatusRegs[N_ISM][STATUS_LEN];
169
unsigned int readOnlyAlarmRegs[N_ISM][ALARM_LEN];
170
unsigned int readOnlyConfigReg[N_ISM][CONTROL_CONFIG_LEN];
171
unsigned int readOnlyControlReg[N_ISM][CONTROL_COMMAND_LEN];
172
unsigned int readWriteControlReg[N_ISM][CONTROL_COMMAND_LEN];
173
174
unsigned int GetStatusReg(int idx, int prod)							{return readOnlyStatusRegs[prod][idx];}
175
unsigned int GetAlarmReg(int idx, int prod)							{return readOnlyAlarmRegs[prod][idx];}
176
void 			 SetConfigReg(int idx, int prod, int val)			   {readOnlyConfigReg[prod][idx] = val;}
177
unsigned int GetConfigReg(int idx, int prod)					    	{return readOnlyConfigReg[prod][idx];}
178
void 			 SetRdControlReg(int idx, int prod, int val)			{readOnlyControlReg[prod][idx] = val;}
179
unsigned int GetRdControlReg(int idx, int prod)						{return readOnlyControlReg[prod][idx];}
180
unsigned int GetWrControlReg(int idx, int prod)						{return readWriteControlReg[prod][idx];}
181
182
void SetStatusReg(int idx, int prod, int ch, int val)
183
{
184
	if (idx == AUTH_INPUTS ||
185
       idx == SUMP_SENSOR ||
186
       idx == SHUNT_VALVE ||
187
       idx == FLOW_SWITCH)
188
	{
189
   	if (val)
190
   		readOnlyStatusRegs[prod][idx] |= BitToMask(ch);
191
      else
192
      	readOnlyStatusRegs[prod][idx] &= ~BitToMask(ch);
193
   }
194
   else if (idx == GPH3_PASSED ||
195
   			idx == PASSED_02 ||
196
   			idx == PASSED_01)
197
   {
198
   	if (val)
199
      	readOnlyStatusRegs[prod][idx]++;
200
   }
201
   else
202
		readOnlyStatusRegs[prod][idx] = val;
203
}
204
205
void SetAlarmReg(int idx, int prod, int ch, int val)
206
{
207
	if (idx == PRES_ALARMS ||
208
       idx == GPH3FAILURES ||
209
       idx == SENSOR_OUTS ||
210
       idx == PRECISION_TEST_FAILURES ||
211
       idx == NO_FLOW_AL ||
212
       idx == DEAD_TURBINE ||
213
       idx == FAILED_TURBINE_CV_WARNING ||
214
       idx == GPH3FAILURES_WARNING)
215
   {
216
      if (val)
217
   		readOnlyAlarmRegs[prod][idx] |= BitToMask(ch);
218
      else
219
      	readOnlyAlarmRegs[prod][idx] &= ~BitToMask(ch);
220
   }
221
   else
222
		readOnlyAlarmRegs[prod][idx] = val;
223
}
224
225
void SetWrControlReg(int idx, int prod, int val)
226
{
227
	if (idx == RESET_ALL_CHANNELS ||
228
       idx == RESET_CHANNEL ||
229
       idx == PRECISION_TEST_01 ||
230
       idx == PRECISION_TEST_02 ||
231
       idx == PRECISION_TEST_ABORT ||
232
       idx == DT_TOP_OFF)
233
	{
234
   	if (val > readOnlyControlReg[prod][idx])
235
			readWriteControlReg[prod][idx] = 1;
236
      else
237
      	readWriteControlReg[prod][idx] = 0;
238
	}
239
   else if (idx == CTL_WRITE_CONFIRM)
240
   {
241
   	readWriteControlReg[0][idx]++;
242
   }
243
   else
244
   	readWriteControlReg[prod][idx] = val;
245
}
246
247
// *****************************************************************************************************
248
249
int BAS_SLAVE_Init()
250
{
251
	int result;
252
   result = 0;
253
254
   memset(readOnlyStatusRegs, 0, sizeof(readOnlyStatusRegs));
255
   memset(readOnlyAlarmRegs, 0, sizeof(readOnlyAlarmRegs));
256
   memset(readOnlyConfigReg, 0, sizeof(readOnlyConfigReg));
257
   memset(readOnlyControlReg, 0, sizeof(readOnlyControlReg));
258
   memset(readWriteControlReg, 0, sizeof(readWriteControlReg));
259
	MODBUS_Serial_Init();
260
   Config.ModBus.ActivityTimer = 0;
261
   return result;
262
}
263
264
#if MB_SLAVE_485
265
	void ser485Tx() {BitWrPortI(PCDR, &PCDRShadow, 1, RS485_TX_ENABLE_BIT);}
266
	void ser485Rx() {BitWrPortI(PCDR, &PCDRShadow, 0, RS485_TX_ENABLE_BIT);}
267
#endif
268
MODBUS_SLAVE_DEBUG
269
int MODBUS_Serial_Init ( void )
270
{	auto float timeout;
271
	char dummy;
272
   unsigned long nowtime;
273
274
	timeout = 5*11*1000.0/(float)BaudRate[Config.ModBus.Baudidx]; // time for 5 bytes in msec
275
   MBS_Serial_timeout = (int)(timeout+.5);	// convert to integer
276
   if ( MBS_Serial_timeout < 2 ) Serial_timeout = 2; // insure minimum delay
277
278
   #if MB_SLAVE_485
279
	   BitWrPortI (PCFR, &PCFRShadow, 1, 0); // Configure Port C bit 0
280
	   //  as Serial Port TxD outupt
281
	   WrPortI (SDCR, &SDCRShadow, 0x00);    // Configure Rort C bit 1
282
	   // to use Serial Port RxD for serial input,
283
	   // async mode, 8 bits, no interrupt
284
      serDopen(BaudRate[Config.ModBus.Baudidx]);
285
      printf("Modbus Slave - RS-485\n");
286
   #else
287
      BitWrPortI (PDFR, &PDFRShadow, 1, 4); // Configure Port D bit 4
288
      // as Serial Port ATxB for serial output
289
      WrPortI (SBCR, &SBCRShadow, 0x10);    // Configure Port D bit 5
290
	   // to use Serial Port ARxB for serial input
291
	   // async mode, 8 bits, no interrupt
292
      serBopen(BaudRate[Config.ModBus.Baudidx]);
293
   #endif
294
295
296
   #if MB_SLAVE_485
297
	   ser485Rx();                         // disable the RS485 transmitter
298
	   serDrdFlush();                      // clear the read FIFO
299
      while (serDrdUsed() > 0)
300
   	{
301
   		serDread(&dummy, 1, 100);
302
      	nowtime =MS_TIMER;
303
      	while (MS_TIMER - nowtime < 10) {}
304
   	}
305
	#else
306
      serBrdFlush();                      // clear the read FIFO
307
      while (serBrdUsed() > 0)
308
   	{
309
   		serBread(&dummy, 1, 100);
310
      	nowtime =MS_TIMER;
311
      	while (MS_TIMER - nowtime < 10) {}
312
   	}
313
   #endif
314
315
	MODBUS_flags0 = 0;						// initialize special flags
316
	return MB_SUCCESS;
317
} // MODBUS_Serial_Init
318
319
/* START FUNCTION DESCRIPTION ********************************************
320
MODBUS_Serial_Tx			<Modbus_Slave_BL26xx.lib>
321
322
SYNTAX:			int MODBUS_Serial_Tx ( char *Packet, int ByteCount );
323
324
DESCRIPTION:	Transmit a Modbus packet to a "downstream" device.
325
					Calculate the CRC and append to the packet.
326
327
PARAMETER1:		address of packet - must have two byte pad at end for
328
					inclusion of CRC word
329
330
PARAMETER2:		number of bytes in the packet
331
332
RETURN VALUE:	MB_SUCCESS
333
334
END DESCRIPTION **********************************************************/
335
336
/*** BeginHeader MODBUS_Slave_Serial_Tx */
337
int MODBUS_Slave_Serial_Tx ( char *Packet, int ByteCount );
338
/*** EndHeader */
339
340
MODBUS_SLAVE_DEBUG
341
int MODBUS_Slave_Serial_Tx ( char *Packet, int ByteCount )
342
{	auto int CalcCRC,i;
343
	Ms txTimeout;
344
// insert CRC
345
#ifndef USE_MODBUS_CRC
346
	CalcCRC = getcrc ( Packet, ByteCount, 0xFFFF );
347
#else
348
	CalcCRC = MODBUS_SLAVE_CRC(Packet, ByteCount);
349
#endif
350
// Backwards for some reason...
351
	Packet[ByteCount+1] = CalcCRC;			// store low byte
352
   Packet[ByteCount] = CalcCRC>>8;	// store high byte
353
	ByteCount+=2;								// adjust for CRC
354
355
#if MODBUS_SLAVE_DEBUG_PRINT & 0x800
356
	printf ( "Ser Tx:" );
357
	for ( i=0; i<ByteCount; i++ ) printf ( " %02X", Packet[i] );
358
	printf ( "\n\r" );
359
#endif
360
   #if MB_SLAVE_485
361
	   ser485Tx();                         // enable the RS485 transmitter
362
	   serDrdFlush();                      // clear the read FIFO
363
	   serDwrite ( Packet, ByteCount );    // send the data
364
	   // This stall if asking for to many points
365
	   txTimeout = MS_TIMER;
366
	 	while ( serDrdUsed() != ByteCount && MS_TIMER < txTimeout + 250); // wait for all bytes to be transmitted
367
	   ser485Rx();                         // disable the RS485 transmitter
368
	   serDrdFlush();                      // clear the read FIFO
369
	   return MB_SUCCESS;                  // show success
370
   #else
371
	   serBrdFlush();                      // clear the read FIFO
372
	   serBwrite ( Packet, ByteCount );    // send the data
373
	   // This stall if asking for to many points
374
	   txTimeout = MS_TIMER;
375
	 	while ( serBrdUsed() != ByteCount && MS_TIMER < txTimeout + 250); // wait for all bytes to be transmitted
376
	   serBrdFlush();                      // clear the read FIFO
377
	   return MB_SUCCESS;                  // show success
378
    #endif
379
} // MODBUS_Serial_Tx
380
381
/* START FUNCTION DESCRIPTION *********************************************
382
MODBUS_Serial_Rx			<Modbus_Slave_BL26xx.lib>
383
384
DESCRIPTION:	Receive the response from the Modbus Slave
385
					Uses the global variable Serial_timeout
386
					It is the responsibility of the caller to handle
387
					a timeout if required.
388
389
PARAMETER1:		address to put the data
390
391
RETURN VALUE:	0 = no message
392
					+n = number of bytes with valid CRC
393
               MB_CRC_ERROR = invalid CRC
394
395
END DESCRIPTION **********************************************************/
396
/*** BeginHeader MODBUS_Slave_Serial_Rx */
397
int MODBUS_Slave_Serial_Rx ( char * DataAddress );
398
/*** EndHeader */
399
400
MODBUS_SLAVE_DEBUG
401
int MODBUS_Slave_Serial_Rx ( char * DataAddress )
402
{	auto int RxCRC, CalcCRC;
403
	auto int ByteCount,i, reg, p1;
404
   auto int backwards;
405
406
   #if MB_SLAVE_485
407
		ByteCount = serDread( DataAddress, 100, Serial_timeout );
408
   #else
409
      ByteCount = serBread( DataAddress, 100, Serial_timeout );
410
   #endif
411
   if ( ByteCount )
412
   {
413
	#if MODBUS_SLAVE_DEBUG_PRINT & 0x800
414
		printf ( "\n\rSer Rx:" );
415
		for ( i=0; i<ByteCount; i++ ) printf ( " %02X", DataAddress[i] );
416
	#endif
417
418
   	ByteCount -= 2;						// adjust for CRC
419
	#ifndef USE_MODBUS_CRC
420
		CalcCRC = getcrc ( DataAddress, ByteCount, 0xFFFF );
421
	#else
422
		CalcCRC = MODBUS_SLAVE_CRC(DataAddress, ByteCount);
423
	#endif
424
   // Why does the modbus master emulator create crc backwards?
425
   /*
426
   backwards = CalcCRC & 0xff;
427
   CalcCRC = (CalcCRC & 0xff00) >> 8;
428
	CalcCRC |= backwards << 8;
429
   */
430
   #if MODBUS_SLAVE_DEBUG_PRINT & 0x400
431
   	reg = DataAddress[2];
432
      reg = (reg<<8) + (int)DataAddress[3];
433
		p1 = DataAddress[4];
434
      p1 = (p1<<8) + (int)DataAddress[5];
435
		printf ( "Ser Rx: Addr=%d Function=%2.2X Reg=%4d P1=%4d\n\r",
436
      	DataAddress[0], DataAddress[1], reg, p1 );
437
	#endif
438
439
		RxCRC = DataAddress[ByteCount+1] & 0x00FF; // LSByte
440
   	i = DataAddress[ByteCount]<<8;	// MSByte
441
   	RxCRC = RxCRC | ( i & 0xFF00 );	// MSbyte
442
443
	#if MODBUS_SLAVE_DEBUG_PRINT & 0x800
444
   	printf ( "  Calc CRC=%04X   Rcvd CRC=%04X\n\r", CalcCRC, RxCRC );
445
	#endif
446
447
	   if ( CalcCRC != RxCRC ) ByteCount = MB_CRC_ERROR;
448
   }
449
   return ByteCount;
450
} // MODBUS_Serial_Rx
451
452
/* START FUNCTION DESCRIPTION *****************************************
453
mbsDigOutRd
454
455
ModBus function code = 0x01
456
457
SYNTAX: 			int mbsDigOutRd ( unsigned OutputNbr, int *pnState )
458
459
DESCRIPTION:	read the specified output.  This is slightly different
460
					than mbDigIn in that this function returns a '1' if the
461
               output is on (low).  It essentially returns the opposite
462
               of the mbDigIn function.
463
464
PARAMETER1:		output number: 0..15
465
466
PARAMETER2:		pointer to destination variable
467
468
RETURN VALUE:	MB_SUCCESS = success
469
					MB_BADADDR = illegal channel
470
               MB_BADDATA = illegal data value
471
               MB_DEVNOTSET = I/O not set as output
472
473
END DESCRIPTION ******************************************************/
474
475
/*** BeginHeader mbsDigOutRd */
476
int mbsDigOutRd ( unsigned OutputNbr, int *pnState );
477
/*** EndHeader */
478
479
MODBUS_SLAVE_DEBUG
480
int mbsDigOutRd ( unsigned OutputNbr, int *pnState )
481
{
482
/*	if ( OutputNbr > 15 ) return MB_BADADDR;
483
	//if( __brdInitFlag == FALSE ) return MB_DEVNOTSET;
484
485
	//*pnState = 1-digIn ( OutputNbr );
486
   */
487
	return MB_SUCCESS;
488
} // mbsDigOutRd
489
490
491
/* START FUNCTION DESCRIPTION *****************************************
492
mbsDigIn
493
494
ModBus function code = 0x02
495
496
SYNTAX:			int mbsDigIn ( unsigned InputNbr, int *pnState )
497
498
DESCRIPTION:	read the specified input
499
500
PARAMETER1:		input number: 0..31
501
						Inputs 0..15 are the DIO signals
502
                  Inputs 16..31 are DIN16..31
503
504
PARAMETER2:		pointer to destination variable
505
						a '1' is returned if the input is high
506
507
RETURN VALUE:	MB_SUCCESS = success
508
					MB_BADADDR = illegal channel
509
               MB_BADDATA = illegal data value
510
               MB_DEVNOTSET = I/O not set as output
511
512
END DESCRIPTION ******************************************************/
513
514
/*** BeginHeader mbsDigIn */
515
int mbsDigIn ( unsigned InputNbr, int *pnState );
516
/*** EndHeader */
517
518
MODBUS_SLAVE_DEBUG
519
int mbsDigIn ( unsigned InputNbr, int *pnState )
520
{
521
/*	if ( InputNbr > 31 ) return MB_BADADDR;
522
	if( __brdInitFlag == FALSE ) return MB_DEVNOTSET;
523
524
	*pnState = digIn ( InputNbr );
525
   */
526
	return MB_SUCCESS;
527
} // mbsDigIn
528
529
530
/* START FUNCTION DESCRIPTION *****************************************
531
mbsRegOutRd
532
533
ModBus function code = 0x03
534
535
SYNTAX:			int mbsRegOutRd ( unsigned OutRegNbr, unsigned *pwValue )
536
537
DESCRIPTION:	read an 8 bit output register
538
539
PARAMETER1:		register number
540
						0 = DIO 0..7		read state of pins and invert (0V = 1)
541
                  1 = DIO 8..15		read state of pins and invert (0V = 1)
542
                  2 = HOUT 0..3		return state of shadow register
543
               Special Registers:
544
               	see mbsRegIn
545
546
PARAMETER2:		pointer to destination variable
547
						for each bit: 0 = output is off, 1 = output is on
548
549
RETURN VALUE:	MB_SUCCESS = success
550
					MB_BADADDR = illegal channel
551
               MB_BADDATA = illegal data value
552
               MB_DEVNOTSET = I/O not set as output
553
END DESCRIPTION ******************************************************/
554
555
/*** BeginHeader mbsRegOutRd */
556
int mbsRegOutRd ( unsigned OutRegNbr, unsigned *pwValue );
557
/*** EndHeader */
558
559
560
MODBUS_SLAVE_DEBUG
561
int mbsRegOutRd ( unsigned OutRegNbr, unsigned *pwValue )
562
{	auto int n;
563
   int MBProd;
564
	//if( __brdInitFlag == FALSE ) return MB_DEVNOTSET;
565
566
567
   // OutRegNbr = OutRegNbr - Offset[Config.ModBus.Offsetidx] - Config.ModBus.Address*1000;
568
   OutRegNbr = OutRegNbr - Offset[Config.ModBus.Offsetidx];  	// Remove offset
569
   MBProd = (int)(OutRegNbr / 1000);                                  // Calc Product / Tank number
570
   OutRegNbr = OutRegNbr - MBProd * 1000;                      // Remove Product number
571
572
   if (OutRegNbr >= MB_GROUP_STATUS && OutRegNbr < STATUS_LEN)
573
   {
574
   	*pwValue = GetStatusReg(OutRegNbr, MBProd);
575
      return MB_SUCCESS;
576
   }
577
   else if (OutRegNbr >= MB_GROUP_ALARM && OutRegNbr < MB_GROUP_ALARM+ALARM_LEN)
578
   {
579
   	*pwValue = GetAlarmReg(OutRegNbr - MB_GROUP_ALARM, MBProd);
580
      return MB_SUCCESS;
581
   }
582
   else if (OutRegNbr >= MB_GROUP_CONFIG && OutRegNbr < MB_GROUP_CONFIG+CONTROL_CONFIG_LEN)
583
   {
584
   	*pwValue = GetConfigReg(OutRegNbr - MB_GROUP_CONFIG, MBProd);
585
      return MB_SUCCESS;
586
   }
587
   else if (OutRegNbr >= MB_GROUP_CONTROL && OutRegNbr < MB_GROUP_CONTROL+CONTROL_COMMAND_LEN)
588
   {
589
   	*pwValue = GetRdControlReg(OutRegNbr - MB_GROUP_CONTROL, MBProd);
590
      return MB_SUCCESS;
591
   }
592
593
   return MB_BADADDR;
594
} // mbsRegOutRd
595
596
597
/* START FUNCTION DESCRIPTION *****************************************
598
mbsRegIn						<Modbus_Slave_BL26xx.LIB>
599
600
NOTE: Modbus_Slave_BL26xx.LIB functions are generally not reentrant.
601
602
ModBus function code = 0x04
603
604
SYNTAX: 			int mbsRegIn ( unsigned InRegNbr, unsigned *pwValue )
605
606
DESCRIPTION:	read an input register: read state of pins (0V = 0)
607
608
PARAMETER1:		register number
609
						0 = DIO 0..7
610
                  1 = DIO 8..15
611
						2 = IN16 - IN23
612
						3 = IN24 - IN31
613
               Special Registers:
614
               	1000 = DIO 0..15 configuration - see digOutConfig
615
                  1001 = HOUT 0..3 configuration - see digHoutConfig
616
						3nnx = Analog Input where nn = A/D channel
617
                  	3nn0, 3nn1 = floating point volts
618
                     3nn2 = integer millivolts
619
                     3003 = integer raw value
620
                  note: see mbsRegOut for gain code storage
621
622
PARAMETER2:		pointer to destination variable
623
624
RETURN VALUE:	MB_SUCCESS = success
625
					MB_BADADDR = illegal channel
626
               MB_BADDATA = illegal data value
627
               MB_DEVNOTSET = I/O not set as output
628
END DESCRIPTION ******************************************************/
629
630
/*** BeginHeader mbsRegIn */
631
int mbsRegIn ( unsigned InRegNbr, unsigned *pwValue );
632
/*** EndHeader */
633
634
MODBUS_SLAVE_DEBUG
635
int mbsRegIn ( unsigned InRegNbr, unsigned *pwValue )
636
{	auto int channel;
637
638
	//if( __brdInitFlag == FALSE ) return MB_DEVNOTSET;
639
640
	return MB_SUCCESS;
641
} // mbsRegIn
642
643
644
/* START FUNCTION DESCRIPTION ********************************************
645
mbsDigOut						<Modbus_Slave_BL26xx.LIB>
646
647
NOTE: Modbus_Slave_BL26xx.LIB functions are generally not reentrant.
648
649
MODBUS command = 0x05, 0x0F
650
651
SYNTAX:     	int mbsdigOut ( unsigned OutputNbr, int state );
652
653
DESCRIPTION:	turn the specified output on or off
654
655
PARAMETER1:		output channel number
656
						0 <= channel <= 15: DIO.00DIO.15
657
						16 <= channel <= 19: Hout0-Hout3 (High-Current)
658
659
PARAMETER2:		output state
660
						0 = turn output off
661
						1 = turn output on
662
							0 <= channel <= 15
663
   	      	     		Connects the load to GND
664
							16 <= channel <= 19
665
		            	   Sinking:	Connects the load to GND
666
								Sourcing: Connects the load to +V
667
668
RETURN VALUE:	MB_SUCCESS = success
669
					MB_BADADDR = illegal channel
670
               MB_BADDATA = illegal data value
671
               MB_DEVNOTSET = I/O not set as output
672
673
SEE ALSO: 		brdInit, digOutConfig
674
675
END DESCRIPTION **********************************************************/
676
677
/*** BeginHeader mbsDigOut */
678
int mbsDigOut ( unsigned OutputNbr, int state );
679
/*** EndHeader */
680
681
MODBUS_SLAVE_DEBUG
682
int mbsDigOut ( unsigned OutputNbr, int state )
683
{
684
	if ( OutputNbr > 19 ) return MB_BADADDR;
685
//	if( __brdInitFlag == FALSE ) return MB_DEVNOTSET;
686
687
   return MB_SUCCESS;
688
} // mbsDigOut
689
690
691
/* START FUNCTION DESCRIPTION *****************************************
692
mbsRegOut
693
694
ModBus function codes = 0x06, 0x10, 0x16 and 0x17,
695
696
SYNTAX: 			int mbsRegOut ( unsigned OutRegNbr, unsigned wValue )
697
698
DESCRIPTION: 	write to an I/O register
699
700
PARAMETER1:		register number
701
						0 = DIO 0..7
702
                  1 = DIO 8..15
703
                  2 = HOUT 0..3
704
               Special Registers:
705
               	1000 = DIO 0..15 configuration - see digOutConfig
706
                  1001 = HOUT 0..3 configuration - see digHoutConfig
707
                  2nnx = Analog Output where nn = D/A nbr
708
                  	2nn0, 2nn1 = floating point volts: see anaOutVolts
709
                     2nn2 = integer millivolts: uses anaOutVolts
710
                     2nn3 = integer raw value: see anaOut
711
                     2nn9 = turn on D/A power: see anaOutPwr
712
						3nnx = Analog Input where nn = A/D channel
713
							3nn8 = integer operating mode: see anaInConfig
714
                     			nn = channel pair: 0..3
715
                     3nn9 = integer range code used for mbsRegIn: 0..7
716
                  1999 = misc. configuration bits
717
718
PARAMETER2:		register value (each bit) for DIO 0..15
719
						0 = turn output off
720
                  1 = turn output on
721
               register values for HOUT 0..3 (4 bits per output)
722
               		HOUT 0 = bits 0..3, ...
723
               	0 = both transistors off = Tri-State
724
                  1 = source (upper transistor on)
725
                  2 = sink (lower transistor on)
726
                  rest = illegal
727
728
RETURN VALUE:	MB_SUCCESS = success
729
					MB_BADADDR = illegal channel
730
               MB_BADDATA = illegal data value
731
               MB_DEVNOTSET = I/O not set as output
732
END DESCRIPTION ******************************************************/
733
734
/*** BeginHeader mbsRegOut */
735
int mbsRegOut ( unsigned OutRegNbr, unsigned wValue );
736
int anaInConfigVal[4];
737
/*** EndHeader */
738
739
// Write Single Register
740
MODBUS_SLAVE_DEBUG
741
int mbsRegOut ( unsigned OutRegNbr, unsigned wValue )
742
{
743
	int MBProd;
744
	//	if( __brdInitFlag == FALSE ) return MB_DEVNOTSET;
745
	OutRegNbr = OutRegNbr - Offset[Config.ModBus.Offsetidx];    // Remove Offset
746
   MBProd = (int)(OutRegNbr / 1000);                                  // Calc Product / Tank number
747
   OutRegNbr = OutRegNbr - MBProd * 1000;                      // Remove Product number
748
749
   if (OutRegNbr >= MB_GROUP_CONFIG && OutRegNbr < MB_GROUP_CONFIG+CONTROL_CONFIG_LEN)
750
   {
751
   	if (wValue != GetConfigReg(OutRegNbr - MB_GROUP_CONFIG, MBProd))
752
      {
753
   		SetConfigReg(OutRegNbr - MB_GROUP_CONFIG, MBProd, wValue);
754
         readOnlyConfigReg[0][CONFIG_WRITE_CONFIRM]++;
755
      }
756
      return MB_SUCCESS;
757
   }
758
   else if (OutRegNbr >= MB_GROUP_CONTROL && OutRegNbr < MB_GROUP_CONTROL+CONTROL_COMMAND_LEN)
759
   {
760
      if (wValue != GetRdControlReg(OutRegNbr - MB_GROUP_CONTROL, MBProd))
761
   	{
762
         SetWrControlReg(OutRegNbr - MB_GROUP_CONTROL, MBProd, wValue);
763
   		SetRdControlReg(OutRegNbr - MB_GROUP_CONTROL, MBProd, wValue);
764
         readOnlyControlReg[0][CTL_WRITE_CONFIRM]++;
765
      }
766
      return MB_SUCCESS;
767
   }
768
   return MB_BADADDR;
769
} // mbsRegOut
770
771
/*** BeginHeader mbsStart, mbsDone */
772
int mbsStart();
773
int mbsDone();
774
/*** EndHeader */
775
int mbsStart() {return MB_SUCCESS;}
776
int mbsDone () {return MB_SUCCESS;}
777
778
/*** BeginHeader
779
*/
780
781
/*** EndHeader */
782
783
784
/*** BeginHeader */
785
#endif
786
/*** EndHeader */