Gerrie de Jager / Mbed 2 deprecated Creatron_RS485

Dependencies:   mbed

dlms_comms.cpp

Committer:
creatron
Date:
2014-11-11
Revision:
8:595258a79939
Parent:
7:cfe1e0eafb7e
Child:
9:d49cdc77f867

File content as of revision 8:595258a79939:

#include "mbed.h"

#include "RawSerial.h"
#include "dlms_comms.h"

//#define DEBUG_DLMS_COMMS 

   // Instantiate the raw serial (2nd uart) Tx then Rx
   RawSerial  rs485(PA_9, PA_10);
  // pin to switch the rs485 buffer direction
  // DigitalOut dir_485 (PB_0);
  DigitalOut dir_485 (D7);
  
/** ---------------------------------------------------------------------------
 * @brief  C O N S T R U C T O R
 */
dlms_comms::dlms_comms (void)
{
    // enable the rs485 buffer receiver, 
    dir_485 = 0;

    // clear the pointers and ring buffer
    rx_head_ptr = 0;
    rx_tail_ptr = 0;
    memset (rx_buffer, 0, sizeof(rx_buffer));

    // transmit empty flag .. need to set buffer
    // in receive mode again after we have transmitted
    // all data characters
//    rs485.attach(this,
//                 &dlms_comms::Tx_interrupt,
//                 //RawSerial::TxIrq
//                 Serial::TxIrq);
    // attach the receiver input to 'run' a method
    
    
    // when characters received
    rs485.attach(this,
                 &dlms_comms::Rx_interrupt,
                 //RawSerial::RxIrq
                 Serial::RxIrq);
    timer = NULL;
    debug_uart = NULL;
    tx_irq_count = 0l;
    rx_irq_count = 0l;
    
    
//        /** Set the flow control type on the serial port
//     *
//     *  @param type the flow control type (Disabled, RTS, CTS, RTSCTS)
//     *  @param flow1 the first flow control pin (RTS for RTS or RTSCTS, CTS for CTS)
//     *  @param flow2 the second flow control pin (CTS for RTSCTS)
//     */
//    rs485.set_flow_control(RTSCTS , //Flow type, 
//                           dir_485, //PB_0, //PinName flow1=NC, 
//                           dir_485 //PB_0 //PinName flow2=NC
//                           );
}
/** ---------------------------------------------------------------------------
 * @brief bq34z110::init_port_expander Put all ports in INPUT mode
 * @param parent_uart  The debug uart class pionter
 * @param parent_timer The main timer (system tick) class pointer
 */
void dlms_comms::init  (RawSerial * parent_uart,
                        Timer     * parent_timer)
{  
    // we use the parent timer and debug port
    debug_uart  = parent_uart; 
    timer       = parent_timer;
//#ifdef DEBUG_DLMS_COMMS    
    //debug_uart->printf ("   init_dlms_comms..\r\n");
//#endif      
}
/** ---------------------------------------------------------------------------
 * @brief dlms_comms::initialise This method initialise the rs485 comms port
 *
 * @param baudrate   The RS485 baudrate
 * @param bits       The RS485 number of bits (8)
 * @param parity     The parity required 'n','o', 'e'
 * @param stop_bits  The number of stop bits 1 or 2
 */
void dlms_comms::initialise (INT_16      baudrate,
                             UINT_8      bits,
                             UINT_8      parity,
                             UINT_8      stop_bits )
{
    // default comms parameters
    SerialBase::Parity my_parity = SerialBase::None;
    tx_irq_count = 0l;
    rx_irq_count = 0l;
    // set the class baudrate
    rs485.baud(baudrate);
    // enable the receiver on the tranceiver buffer chip
    dir_485 = 0;
    // clear the ring buffer
    rx_head_ptr = 0;
    rx_tail_ptr = 0;
    memset (rx_buffer, 0, sizeof(rx_buffer));
    // set the enum parity as required by class
    switch (parity)
    {
    default:
    case 'n' :
        my_parity = SerialBase::None;
        break;
    case 'o':
        my_parity = SerialBase::Odd;
        break;
    case 'e':
        my_parity = SerialBase::Even;
        break;
    }
    // lets doit .. config the rs485 now
    rs485.format((int) bits,
                 my_parity,
                 (int) stop_bits);
//#  ifdef DEBUG_DLMS_COMMS    
     //debug_uart->printf ("   init_dlms_comms..Baudrate (%d) %d bits Parity=%c\r\n",
     //                     baudrate, bits, parity);
//#  endif                          
     // dummy send packet to rs485 
     //send_packet ("\r\nHello cruel world\r\n",12);       
     if ( rs485.readable())
          rs485.getc();
}
/** ---------------------------------------------------------------------------
 * @brief dlms_comms::get_dir485 . This method  returns the state of the rs485
 * direction
 */
bool dlms_comms::get_dir485 (void)
{
    return dir_485;
}
/** ---------------------------------------------------------------------------
 * @brief dlms_comms::Tx_interrupt
 */
void dlms_comms::Tx_interrupt(void)
{
    tx_irq_count++;
    // enable the receiver, we are finito with the transmission of characters
    // this changes the direction on the transceiver buffer
    if (dir_485 == 1)
        dir_485 = 0;       
}
/** ---------------------------------------------------------------------------
 * @brief dlms_comms::Rx_interrupt . This method received all characters from
 * the uart and saved it in a ring buffer, 256 bytes long. The CPU only has 16
 * byte fifo, this makes it a 256 bit fifo
 */
void dlms_comms::Rx_interrupt(void)
{
    UINT_8 value;
    rx_irq_count++;
    // read the uart and place character in ring buffer
    value = rs485.getc();
    rx_buffer[rx_head_ptr++] = value;
}
/** ---------------------------------------------------------------------------
 * @brief dlms_comms::available This method return if we have any characters
 * available (received on the rs485 port)
 * @return true if characters received on the rs485
 */
bool dlms_comms::char_available (void)
{
    if (rx_head_ptr == rx_tail_ptr)
        // nope
        return false;
    else
        return true;
}
/** ---------------------------------------------------------------------------
 * @brief dlms_comms::get_char This method return the last character received
 * on the rs485 port
 * @return Unsigned byte
 * @note The user must make sure that characters are available before, else
 * this method shall wait for the next character, no timeouts yet
 */
UINT_8 dlms_comms::get_char (void)
{
    // we have to wait for at least on charcter in the ring buffer
    while (char_available() == false);
    // return the character
    return (rx_buffer[rx_tail_ptr++]);
}
/** ---------------------------------------------------------------------------
 * @brief dlms_comms::send_packet This method sends a serial packet data to the
 * rs485 bus, the directoion of the tranceiver chip is changed to transmit and
 * the packet is tranmitted.
 * @param ptr     Pointer address for start of the packet
 * @param length  Packet length
 * @note          The direction is changed with a interrupt when the transmitter
 *                is empty
 */
void dlms_comms::send_packet (const UINT_8  *ptr,
                              const UINT_8   length)
{
    // local stack variable
    UINT_8 * tmp_ptr =(UINT_8 *) ptr;

    // change the tranceiver direction to output
    dir_485 = 1;
    for (UINT_8 i= 0; i < length; i++)
    {
        rs485.putc (*tmp_ptr++);
    }
    //
    rs485.attach(this,
                 &dlms_comms::Tx_interrupt,
                Serial::TxIrq);
}
UINT_64 dlms_comms::ret_rx_irq_count (void)
{
    return rx_irq_count;
}
UINT_64 dlms_comms::ret_tx_irq_count (void)
{
    return tx_irq_count;
}
bool dlms_comms::ret_dir_485 (void)
{
    return dir_485;
}
//----[ the end ]--------------------------------------------------------------