// TS-1400 Coil-toggle example.
// Written by Michael D Peters for Technologic Systems, Inc.
// Copyright March 22, 2013
//
// This code assumes six relays on a TS-1400 that is configured
// in legacy mode, 115200 baud, 8, N, 1, Device address 0xAC.
//
// This code assumes the use of the Technologic Systems XUART
// controller, xuartctl, and the appropriately modified version
// of Libmodbus.  Patch files available near here:
// http://forum.embeddedarm.com/
//
// These settings are modifiable in the #define block below.
//
// This program demonstrates both methods of setting coils on
// the TS-1400.
// First by setting coils using the holding register address.
// Second by setting individual coils using the write coil command.

#include <stdio.h>
#include <stdlib.h>
#include <modbus.h>
#include <errno.h>

#define DEVICE_ID 0xAC
#define SPEED 115200
#define PORT "127.0.0.1:7350"
#define RELAY_REGISTER 0x40

modbus_t *mb;

int main(int argc, char* argv[])
{
	int c = 0;

	// modbus setup
	mb = modbus_new_rtu(PORT, SPEED, 'N', 8, 1);
	if(!mb){
		fprintf(stderr, "Unable to open bus at port %s.\n", PORT);
		return 0;
	}

	modbus_set_debug(mb, (argc > 1));
	modbus_set_slave(mb, DEVICE_ID);
	modbus_connect(mb);

	// Demo functions
	printf("Ticking relay pattern...\n");
	c = set_multiple_relays();
	if(c == -1){
		return 0; // error output by function.
	}

	printf("Ticking individual relays...\n");
	c= set_single_relay();
	if(c == -1){
		return 0; // error output by function.
	}

	return 0;
}

// throws relays in a 24 position countup -- that's 64 iterations.
// returns -1 and prints stderr if there was a problem, 
// returns 1 if no trouble was detected.
int set_multiple_relays()
{
	uint16_t c = 0;
	int d = 0;
	for(c = 0; c < 64; c++){
		d = modbus_write_register(mb, RELAY_REGISTER, c);
		usleep(100000);
		if(d == -1){
			fprintf(stderr, "Problem with write.  Error %d: %s", 
				errno, modbus_strerror(errno));
			return -1;
		}
	}
	return 1;
}

// Throws relays individually using the write relay modbus command.
// Returns -1 if error condition and writes an error to stderr.  Returns 1 otherwise.
int set_single_relay()
{
	int c = 0;
	int d = 0;
	d = modbus_write_register(mb, RELAY_REGISTER, 0);
	while(c<6){
		d = modbus_write_bit(mb, c, 0xffff);
		usleep(1000000);
		d = modbus_write_bit(mb, c++, 0x0);
		if(d == -1){
			fprintf(stderr, "Problem with write.  Error %d:  %s", 
				errno, modbus_strerror(errno));
			return d;
		}
	}
	return 1;
}
