DMX Library for STM devices

Dependents:   DISCO-F746NG_DMX-Test

Fork of DMX by Suga koubou

DMX.cpp

Committer:
Gottfried
Date:
2015-12-12
Revision:
17:b87addd12d20
Parent:
16:4eeb749806e5
Child:
18:e5e5eca21b4a

File content as of revision 17:b87addd12d20:

/*
 * DMX512 send/recv library
 * Copyright (c) 2013 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file
 * @brief DMX512 send/recv
 */

#include "mbed.h"
#include "DMX.h"

// pragma does'nt work?
#pragma GCC diagnostic ignored "-Wreorder"

DMX::DMX (PinName p_tx, PinName p_rx, unsigned int size) :
  _dmx(p_tx, p_rx),
  myDMXSize(size),
  is_recived(0),
  is_sent(0),
  mode_tx(DMX_MODE_STOP),
  mode_rx(DMX_MODE_BEGIN)
{
  data_tx = new char[myDMXSize];
  data_rx = new char[myDMXSize];
  
  clear();

  _uart = new DUMMY_UART_TypeDef;
//  NVIC_SetPriority(UART_IRQn, 1);

  _dmx.baud(250000);
  _dmx.format(8, Serial::None, 2);
  _dmx.attach(this, &DMX::int_rx, Serial::RxIrq);
}

DMX::~DMX()
{
  delete _uart;
  delete[] data_tx;
  delete[] data_rx;
}

void DMX::put(int addr, int data)
{
  if(addr < 0 || addr >= myDMXSize)
    return;
  data_tx[addr] = data;
}

void DMX::put(unsigned char *buf, int addr, int len)
{
  if(!len)
    len = myDMXSize;
  
  if(addr < 0 || addr >= myDMXSize)
    return;
  if(len > myDMXSize - addr)
    len = myDMXSize - addr;
  memcpy(&data_tx[addr], buf, len);
}

int DMX::get(int addr)
{
  if(addr < 0 || addr >= myDMXSize) 
    return -1;
  
  return data_rx[addr];
}

void DMX::get(unsigned char *buf, int addr, int len)
{
  if(!len)
    len = myDMXSize;

  if(addr < 0 || addr >= myDMXSize)
    return;
  if(len > myDMXSize - addr)
    len = myDMXSize - addr;
  memcpy(buf, &data_rx[addr], len);
}

void DMX::int_timer()
{
  switch(mode_tx)
  {
    case DMX_MODE_BEGIN:
        // Break Time
        timeout01.detach();
        _uart->LCR |= (1 << 6);
        mode_tx = DMX_MODE_BREAK;
        timeout01.attach_us(this, &DMX::int_timer, DMX_TIME_BREAK);
        break;

    case DMX_MODE_BREAK:
        // Mark After Break
        timeout01.detach();
        _uart->LCR &= ~(1 << 6);
        mode_tx = DMX_MODE_MAB;
        timeout01.attach_us(this, &DMX::int_timer, DMX_TIME_MAB);
        break;

    case DMX_MODE_MAB:
        // Start code
        timeout01.detach();
        addr_tx = 0;
        mode_tx = DMX_MODE_DATA;
        _dmx.attach(this, &DMX::int_tx, Serial::TxIrq);
#ifdef DMX_UART_DIRECT
        while(!(_uart->LSR & (1<<5)));
        _uart->THR = DMX_START_CODE;
#else
        _dmx.putc(DMX_START_CODE);
#endif
        break;
  }
}

void DMX::int_tx()
{
  // Data
  if(mode_tx == DMX_MODE_DATA)
  {
    if(addr_tx < myDMXSize)
    {
#ifdef DMX_UART_DIRECT
      _uart->THR = (uint8_t)data_tx[addr_tx];
#else
      _dmx.putc(data_tx[addr_tx]);
#endif
      addr_tx ++;
    }
    else
    {
      _dmx.attach(0, Serial::TxIrq);
      mode_tx = DMX_MODE_BEGIN;
      is_sent = 1;
      timeout01.attach_us(this, &DMX::int_timer, DMX_TIME_BETWEEN);
    }
  }
}

void DMX::int_rx()
{
  int flg, dat;

  flg = _uart->LSR;
#ifdef DMX_UART_DIRECT
  dat = _uart->RBR;
#else
  dat = _dmx.getc();
#endif

  if (flg & ((1 << 7)|(1 << 3)|(1 << 4)))
  {
    // Break Time
    if(addr_rx >= 24 && mode_rx == DMX_MODE_DATA)
    {
      is_recived = 1;
    }
    mode_rx = DMX_MODE_BREAK;
    return;
  }

  if(mode_rx == DMX_MODE_BREAK)
  {
    // Start Code
    if (dat == DMX_START_CODE)
    {
      addr_rx = 0;
      mode_rx = DMX_MODE_DATA;
    }
    else
    {
      mode_rx = DMX_MODE_ERROR;
    }

  }
  else if(mode_rx == DMX_MODE_DATA)
  {
    // Data
    data_rx[addr_rx] = dat;
    addr_rx ++;

    if (addr_rx >= myDMXSize)
    {
      is_recived = 1;
      mode_rx = DMX_MODE_BEGIN;
    }
  }
}

void DMX::start()
{
  if (mode_tx == DMX_MODE_STOP)
  {
    mode_tx = DMX_MODE_BEGIN;
    is_sent = 0;
    timeout01.attach_us(this, &DMX::int_timer, DMX_TIME_BETWEEN);
  }
}

void DMX::stop()
{
  _dmx.attach(0, Serial::TxIrq);
  timeout01.detach();
  mode_tx = DMX_MODE_STOP;
}

void DMX::clear()
{
  memset(data_tx, 0, myDMXSize);
  memset(data_rx, 0, myDMXSize);
}