/*
 * modbus.c
 *
 *  Created on: Mar 30, 2012
 *      Author: qwer1
 */

#include "modbus.h"
#include "ul_timing.h"
#include "usart.h"
#include "config.h"
#include "adc.h"

struct modbus_struct modbus;

struct modbus_reg_struct modbus_regs[] = {
	{&project_signature, MODBUS_REG_TY_U16, 0, 0},
	{&project_version,   MODBUS_REG_TY_U16, 0, 0},
	{&process.run, MODBUS_REG_TY_U8, 1, 1},
	{&config.current_program, MODBUS_REG_TY_U8, 1, 1},
	{&config.current_step, MODBUS_REG_TY_U8, 1, 1},
	{&process.program_time, MODBUS_REG_TY_U32H, 0, 0},
	{&process.program_time, MODBUS_REG_TY_U32L, 0, 0},
	{&process.step_timer, MODBUS_REG_TY_U16, 0, 0},
	{&t_cold,  MODBUS_REG_TY_S16, 0, 0},
	{&t_tc[0], MODBUS_REG_TY_S16, 0, 0},
	{&t_tc[1], MODBUS_REG_TY_S16, 0, 0},
	{&t_tc[2], MODBUS_REG_TY_S16, 0, 0},
	{&t_tc[3], MODBUS_REG_TY_S16, 0, 0},
};
enum modbus_regs_nums {
	modbus_reg_work_mode,
	modbus_reg_current_program,
	modbus_reg_current_step,
	modbus_reg_step_timer,
	modbus_reg_t_cold,
	modbus_reg_t_tc0,
	modbus_reg_t_tc1,
	modbus_reg_t_tc2,
	modbus_reg_t_tc3,
};

void setup_modbus(void) {
	modbus_reset(&modbus);
	modbus.addr   = 33;
	modbus.mode   = MODBUS_MO_RX;
	modbus.master = 0;
	modbus.regs_addr = MODBUS_REGS_ADDR;
	modbus.regs_num = MODBUS_REGS_NUM;
	modbus.regs = NULL;

	ptx_add( pt_modbus, NULL, PTX_FLAG_RUN);
}

PT_THREAD( pt_modbus( struct pt *pt, struct ptx *ptx ) ) {

	//process Modbus timeout
	if (t_1ms && (modbus.mode == MODBUS_MO_RX)) {
		if (++modbus.timeout >= MODBUS_TIMEOUT) {
			modbus_reset(&modbus);
		}
	}

	PT_BEGIN(pt);
	while (1) {

		//new byte received
		if (RBUF_NONEMPTY(&usart_rx_buf)) {
			usart_modbus_mode = 1; //byte received - switch to Modbus mode
//debug_led1 ^= 1;

			if (modbus_slave_receive(&modbus, RBUF_GET(&usart_rx_buf))) {
debug_led1 ^= 1;
				//create response packet
				U8 size = modbus_slave_respond(&modbus);
				if (size > 0) {
debug_led2 ^= 1;
//log_U8(size);
					modbus.mode = MODBUS_MO_TX;
					//delay before TX
//					delay_us(MODBUS_TX_DELAY);
//					PTX_DELAY_MS(MODBUS_TX_DELAY);
					//copy response packet to TX buffer
					RBUF_WR_BUF8(&usart_tx_buf, &(modbus.buf[0]), size);
					PT_WAIT_WHILE(pt, (RBUF_NONEMPTY(&usart_tx_buf)));
					modbus.mode = MODBUS_MO_RX;
				}
				//reset structure
				modbus_reset(&modbus);
			}
			RBUF_INC_RD(&usart_rx_buf);
		}
		PT_YIELD(pt);
	}
	PT_END(pt);
}

U16 modbus_reg_get(U16 reg_num) {
	return modbus_reg_rd(&modbus_regs[0], reg_num);
}

void modbus_reg_set(U16 reg_num, S16 reg_val) {
	modbus_reg_wr(&modbus_regs[0], reg_num, reg_val);
}
