/* * ModbusRTUTransceiver.cpp * * Author: Aleksey Gerasimenko * gerasimenko.aleksey.n@gmail.com */ #include "MODBUSRTU/ModbusRTUTransceiver.h" namespace MODBUSRTU { //CONSTRUCTOR //ModbusRTUTransceiver::ModbusRTUTransceiver(DSP28335::SCIBase& sciport, DSP28335::CPUTimers& cputimer, MODBUSRTU::ModbusRTUCRC& crc): ModbusRTUTransceiver::ModbusRTUTransceiver(DSP28335::SCIBase& sciport, DSP28335::MeasureTimeInterval& interval_measure, MODBUSRTU::ModbusRTUCRC& crc): m_sci_port(sciport), m_sci_config(), m_node_id(0), // m_state_machine(MODBUSRTU::SCAN), m_event(MODBUSRTU::ENTRY), // //m_interval(cputimer.CPUTimer), m_interval_measure(interval_measure), m_interval_pause((Uint32)0), m_interval_b5((Uint32)0), m_interval_b75((Uint32)0), m_interval_1b((Uint32)0), m_interval_1b25((Uint32)0), m_interval_1b5((Uint32)0), m_interval_1b75((Uint32)0), m_interval_3b5((Uint32)0), m_interval_freeze((Uint32)0), m_interval_current((Uint32)0), // m_rx_buffer(), m_tx_buffer(), m_rx_count(0), m_tx_count(0), m_tx_length(0), // m_aux_rx_buf(0), m_aux_rx_count(0), m_aux_tx_buf(0), m_aux_tx_count(0), // m_crc_status(false), m_crc(crc), m_crc_rx_frame(0), m_crc_tx_frame(0), // m_rx_external_buffer(m_rx_buffer), m_tx_external_buffer(m_tx_buffer), m_rx_messaage_length(&m_rx_count), m_tx_message_length(&m_tx_count), // m_destination(0), m_source_start(0), m_source_end(0), m_copy_length(0), // _execute(&ModbusRTUTransceiver::_execute_transceiver), _frame_transceiver(&ModbusRTUTransceiver::_frame_receive_node_id), // _re_de_setup(&DSP28335::GPIO::gpio_scib_re_de_setup), _driver_enable(&DSP28335::GPIO::gpio_scib_re_de_set), _receiver_enable(&DSP28335::GPIO::gpio_scib_re_de_clear) // {}//CONSTRUCTOR void ModbusRTUTransceiver::setup(ModbusRTUTransceiverSetup& setup) { //m_interval.setup(); _re_de_setup = setup.gpio_re_de_setup; _driver_enable = setup.gpio_driver_enable; _receiver_enable = setup.gpio_receiver_enable; (*_re_de_setup)(); _set_receive_node_id(); // }// // void ModbusRTUTransceiver::configure(ModbusRTUTransceiverConfiguration& config) { m_sci_config = config.config; m_node_id = config.node_id; if(!m_sci_port.compare_configuration(m_sci_config)) { m_sci_port.set_configuration(m_sci_config); // }//if switch(m_sci_config.baudrate) { case DSP28335::BR2400: {m_interval_b5 = (Uint32)250000; m_interval_b75 = (Uint32)375000; m_interval_1b = (Uint32)500000; m_interval_1b25 = (Uint32)625000; m_interval_1b5 = (Uint32)750000; m_interval_1b75 = (Uint32)875000; m_interval_3b5 = (Uint32)1750000; m_interval_freeze = (Uint32)2000000; break;} case DSP28335::BR4800: {m_interval_b5 = (Uint32)125000; m_interval_b75 = (Uint32)187500; m_interval_1b = (Uint32)250000; m_interval_1b25 = (Uint32)312500; m_interval_1b5 = (Uint32)375000; m_interval_1b75 = (Uint32)250000; m_interval_3b5 = (Uint32) 875000; m_interval_freeze = (Uint32)1000000; break;} case DSP28335::BR9600: {m_interval_b5 = (Uint32) 62500; m_interval_b75 = (Uint32) 93750; m_interval_1b = (Uint32)125000; m_interval_1b25 = (Uint32)156250; m_interval_1b5 = (Uint32)187500; m_interval_1b75 = (Uint32)218750; m_interval_3b5 = (Uint32) 437500; m_interval_freeze = (Uint32) 500000; break;} case DSP28335::BR19200: {m_interval_b5 = (Uint32) 31250; m_interval_b75 = (Uint32) 46875; m_interval_1b = (Uint32) 62500; m_interval_1b25 = (Uint32)78125; m_interval_1b5 = (Uint32) 93750; m_interval_1b75 = (Uint32)109375; m_interval_3b5 = (Uint32) 218750; m_interval_freeze = (Uint32) 250000; break;} case DSP28335::BR38400: {m_interval_b5 = (Uint32)15625; m_interval_b75 = (Uint32)23437; m_interval_1b = (Uint32) 31250; m_interval_1b25 = (Uint32)39062; m_interval_1b5 = (Uint32) 46875; m_interval_1b75 = (Uint32) 54687; m_interval_3b5 = (Uint32) 109375; m_interval_freeze = (Uint32) 125000; break;} default: {m_interval_b5 = (Uint32)62500; m_interval_b75 = (Uint32)93750; m_interval_1b = (Uint32)125000; m_interval_1b25 = (Uint32)156250; m_interval_1b5 = (Uint32)187500; m_interval_1b75 = (Uint32)218750; m_interval_3b5 = (Uint32) 437500; m_interval_freeze = (Uint32) 500000; break;} }//switch m_interval_pause = m_interval_1b * 0.1; //m_interval_pause = m_interval_1b * 0.2; _set_receive_node_id(); // }// // void ModbusRTUTransceiver::port_reset() { m_sci_port.set_configuration(m_sci_config); _set_receive_node_id(); // }// // bool ModbusRTUTransceiver::compare_state(MODBUSRTU::transceiver_state_machine_t state_machine) { return m_state_machine == state_machine; // }// // void ModbusRTUTransceiver::execute() { (this->*_execute)(); // }// // void ModbusRTUTransceiver::_execute_transceiver() { if(m_sci_port.SciRegs.SCIRXST.bit.BRKDT) { _set_break_condition(); // }//if // (this->*_frame_transceiver)(); // }// // void ModbusRTUTransceiver::_execute_break() { //m_interval_current = m_interval.interval(); // }// // void ModbusRTUTransceiver::setRXBuffer(uint16_t *bufferStart, uint16_t *messageLen) { m_rx_external_buffer = bufferStart; m_rx_messaage_length = messageLen; // }// // void ModbusRTUTransceiver::setTXBuffer(uint16_t *bufferStart, uint16_t *messageLen) { m_tx_external_buffer = bufferStart; m_tx_message_length = messageLen; // }// // // #pragma CODE_SECTION("ramfuncs"); void ModbusRTUTransceiver::_set_receive_node_id() { m_state_machine = MODBUSRTU::SCAN; _frame_transceiver = &ModbusRTUTransceiver::_frame_receive_node_id; _execute = &ModbusRTUTransceiver::_execute_transceiver; (*_receiver_enable)(); // }// // // #pragma CODE_SECTION("ramfuncs"); void ModbusRTUTransceiver::_set_receive_function() { m_state_machine = MODBUSRTU::RECEIVE; _frame_transceiver = &ModbusRTUTransceiver::_frame_receive_function; _execute = &ModbusRTUTransceiver::_execute_transceiver; (*_receiver_enable)(); // }// // // #pragma CODE_SECTION("ramfuncs"); void ModbusRTUTransceiver::_set_receive_data() { m_state_machine = MODBUSRTU::RECEIVE; _frame_transceiver = &ModbusRTUTransceiver::_frame_receive_data; _execute = &ModbusRTUTransceiver::_execute_transceiver; (*_receiver_enable)(); // }// // // #pragma CODE_SECTION("ramfuncs"); void ModbusRTUTransceiver::_set_wait_response() { m_state_machine = MODBUSRTU::WAIT_RESPONSE; _frame_transceiver = &ModbusRTUTransceiver::_frame_wait_response; _execute = &ModbusRTUTransceiver::_execute_transceiver; (*_receiver_enable)(); // }// // // #pragma CODE_SECTION("ramfuncs"); void ModbusRTUTransceiver::_set_transmit_data() { m_state_machine = MODBUSRTU::TRANSMIT; _frame_transceiver = &ModbusRTUTransceiver::_frame_transmit_data; _execute = &ModbusRTUTransceiver::_execute_transceiver; (*_driver_enable)(); // }// // // #pragma CODE_SECTION("ramfuncs"); void ModbusRTUTransceiver::_set_break_condition() { m_state_machine = MODBUSRTU::BREAK; _frame_transceiver = &ModbusRTUTransceiver::_frame_break_condition; _execute = &ModbusRTUTransceiver::_execute_break; (*_receiver_enable)(); // }// // // #pragma CODE_SECTION("ramfuncs"); void ModbusRTUTransceiver::_frame_receive_node_id() { if(m_sci_port.SciRegs.SCIRXST.bit.RXRDY) { m_aux_rx_buf = m_sci_port.SciRegs.SCIRXBUF.bit.RXDT; while(m_sci_port.SciRegs.SCIRXST.bit.RXRDY){} if((m_node_id == m_aux_rx_buf)||(MODBUSRTU_FUNCTION_BROADCAST == m_aux_rx_buf)) { m_rx_buffer[0] = m_aux_rx_buf; m_aux_rx_count = 1; m_interval_measure.start(); _set_receive_function(); // }//if } // }// // // #pragma CODE_SECTION("ramfuncs"); void ModbusRTUTransceiver::_frame_receive_function() { if(m_sci_port.SciRegs.SCIRXST.bit.RXRDY) { m_aux_rx_buf = m_sci_port.SciRegs.SCIRXBUF.bit.RXDT; while(m_sci_port.SciRegs.SCIRXST.bit.RXRDY){} if(//(MODBUSRTU_FUNCTION_BROADCAST == m_aux_rx_buf)|| (MODBUSRTU_FUNCTION_READ_COIL_STATUS == m_aux_rx_buf)|| //(MODBUSRTU_FUNCTION_READ_INPUT_STATUS == m_aux_rx_buf)|| (MODBUSRTU_FUNCTION_READ_HOLDING_REGISTERS == m_aux_rx_buf)|| //(MODBUSRTU_FUNCTION_READ_INPUT_REGISTERS == m_aux_rx_buf)|| (MODBUSRTU_FUNCTION_FORCE_SINGLE_COIL == m_aux_rx_buf)|| (MODBUSRTU_FUNCTION_PRESET_SINGLE_REGISTER == m_aux_rx_buf)|| (MODBUSRTU_FUNCTION_FORCE_MULTIPLE_COILS == m_aux_rx_buf)|| (MODBUSRTU_FUNCTION_PRESET_MULTIPLE_REGISTERS == m_aux_rx_buf)) { m_rx_buffer[1] = m_aux_rx_buf; m_aux_rx_count = 2; m_interval_measure.start(); _set_receive_data(); // } else { // wrong function, break receive m_interval_measure.stop(); _set_receive_node_id(); // }//if else // } else { m_interval_current = m_interval_measure.interval(); if(m_interval_current > m_interval_1b5) { // exceed time interval, break receive m_interval_measure.stop(); _set_receive_node_id(); // }//if // }//if else // }// // #pragma CODE_SECTION("ramfuncs"); void ModbusRTUTransceiver::_frame_receive_data() { if(m_sci_port.SciRegs.SCIRXST.bit.RXRDY) { m_aux_rx_buf = m_sci_port.SciRegs.SCIRXBUF.bit.RXDT; while(m_sci_port.SciRegs.SCIRXST.bit.RXRDY){} m_rx_buffer[m_aux_rx_count] = m_aux_rx_buf; m_aux_rx_count++; m_interval_measure.start(); if(m_aux_rx_count >= 256) { // exceed count, break receive m_interval_measure.stop(); _set_receive_node_id(); // }//if // } else { m_interval_current = m_interval_measure.interval(); if(m_interval_current >= m_interval_1b5) { // // count must be more then 4 if(m_aux_rx_count > 4) { // stop receive, frame is ended // check message m_rx_count = m_aux_rx_count; m_crc_calculate = m_crc.calculate(m_rx_buffer, m_rx_count - 2); m_crc_rx_frame = (m_rx_buffer[m_rx_count - 1] << 8) | m_rx_buffer[m_rx_count - 2]; m_crc_status = m_crc_calculate == m_crc_rx_frame ? true : false; if(m_crc_status) { m_destination = m_rx_external_buffer; m_source_start = m_rx_buffer; m_source_end = m_rx_buffer + m_rx_count - 1; m_copy_length = m_rx_count; *m_rx_messaage_length = m_rx_count; m_event = MODBUSRTU::RXREADY; //_frame_copy(); _frame_copy_erase(); _set_wait_response(); // } else { m_interval_measure.stop(); _set_receive_node_id(); // }//if else // }// else { m_interval_measure.stop(); _set_receive_node_id(); // }// if else // }//if // }//if else // }// // // #pragma CODE_SECTION("ramfuncs"); void ModbusRTUTransceiver::_frame_wait_response() { if(m_sci_port.SciRegs.SCIRXST.bit.RXRDY) { m_aux_rx_buf = m_sci_port.SciRegs.SCIRXBUF.bit.RXDT; while(m_sci_port.SciRegs.SCIRXST.bit.RXRDY){} // error protocol, reset message m_interval_measure.stop(); _set_receive_node_id(); // } else { m_interval_current = m_interval_measure.interval(); if(m_interval_current >= m_interval_3b5) { m_interval_measure.stop(); _set_receive_node_id(); // } else { if(*m_tx_message_length != 0) { // copy external tx buffer m_tx_length = *m_tx_message_length; m_source_start = m_tx_external_buffer; m_source_end = m_tx_external_buffer + m_tx_length - 1; m_destination = m_tx_buffer; //_frame_copy_erase(); _frame_copy(); *m_tx_message_length = 0; m_tx_count = 0; _set_transmit_data(); _frame_transmit_data(); m_interval_measure.stop(); // }//if // }//if else // }//if else // }// // // #pragma CODE_SECTION("ramfuncs"); void ModbusRTUTransceiver::_frame_transmit_data() { if(m_sci_port.SciRegs.SCICTL2.bit.TXRDY & m_sci_port.SciRegs.SCICTL2.bit.TXEMPTY) { // data was transmitted if(m_tx_count >= m_tx_length) { // all message was transmitted // break transmit mode, go to the receive mode _set_receive_node_id(); // } else { m_sci_port.SciRegs.SCITXBUF = m_tx_buffer[m_tx_count]; while(m_sci_port.SciRegs.SCICTL2.bit.TXEMPTY == 1){} m_tx_count++; // }//if else // }// if // }// // // #pragma CODE_SECTION("ramfuncs"); void ModbusRTUTransceiver::_frame_break_condition() { // }// // // #pragma CODE_SECTION("ramfuncs"); inline void ModbusRTUTransceiver::_frame_copy() { while(m_source_start <= m_source_end) { *m_destination++ = *m_source_start++; // }//while // }// // // #pragma CODE_SECTION("ramfuncs"); inline void ModbusRTUTransceiver::_frame_copy_erase() { while(m_source_start <= m_source_end) { *m_destination++ = *m_source_start; *m_source_start++ = 0; // }//while // }// // // #pragma CODE_SECTION("ramfuncs"); void ModbusRTUTransceiver::_frame_copy(uint16_t *source, uint16_t length, uint16_t *destination) { m_destination = destination; m_source_start = source; m_source_end = destination + length - 1; m_copy_length = length; while(m_source_start <= m_source_end) { *m_destination++ = *m_source_start++; // }//while // }// // } /* namespace MODBUSRTU */