DMX512, RDM send/recv library http://mbed.org/users/okini3939/notebook/dmx512

Dependents:   dmx_test ArtNodeLED SPK-DVIMXR SPK-DMXer ... more

DMX512 send/recv library

DMX512 is protocol for lighting.

調光プロトコル DMX512 を送受信するライブラリです。

see: http://mbed.org/users/okini3939/notebook/dmx512/

LPC1114 support is thanks to Stanly Chen

DMX.cpp

Committer:
okini3939
Date:
2017-10-20
Revision:
19:ae8fd2ba7c53
Parent:
18:69d65ca92bcc

File content as of revision 19:ae8fd2ba7c53:

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

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

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


DMX::DMX (PinName p_tx, PinName p_rx, PinName p_xmit) : _dmx(p_tx, p_rx) {

    if (p_xmit == NC) {
        _xmit = NULL;
    } else {
        _xmit = new DigitalOut(p_xmit, XMIT_RX);
    }
    clear();
//    mode_tx = DMX_MODE_BEGIN;
    mode_tx = DMX_MODE_STOP;
    mode_rx = DMX_MODE_BEGIN;
    is_received = 0;
    is_sent    = 0;
    memset(data_tx, 0, sizeof(data_tx));
    memset(data_rx, 0, sizeof(data_rx));
    time_break = DMX_TIME_BREAK;
    time_mab   = DMX_TIME_MAB;
    time_mbb   = DMX_TIME_MBB;

#ifdef RDM_ENABLE
    mode_rdm = 0;
    rdm_mute = 0;
    rdm_msgcount = 0;
    rdm_transno = 0;
    cb_RdmParser = NULL;
    buf_uid_size = 0;
#endif

#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
    if (p_rx == P0_3) {
      _uart = (LPC_UART_TypeDef*)LPC_UART0;
      NVIC_SetPriority(UART0_IRQn, 1);
    } else
    if (p_rx == p14) {
      _uart = (LPC_UART_TypeDef*)LPC_UART1;
      NVIC_SetPriority(UART1_IRQn, 1);
    } else
    if (p_rx == p27) {
      _uart = LPC_UART2;
      NVIC_SetPriority(UART2_IRQn, 1);
    } else
    if (p_rx == p10) {
      _uart = LPC_UART3;
      NVIC_SetPriority(UART3_IRQn, 1);
    }
#elif defined(TARGET_LPC4088)
    if (p_rx == p10 || p_rx == P0_26 || p_rx == P4_29) {
      _uart = LPC_UART3;
      NVIC_SetPriority(UART3_IRQn, 1);
    } else
    if (p_rx == p31) {
      _uart = (LPC_UART_TypeDef*)LPC_UART4;
      NVIC_SetPriority(UART4_IRQn, 1);
    } else
    if (p_rx == P0_3) {
      _uart = LPC_UART0;
      NVIC_SetPriority(UART0_IRQn, 1);
    } else
    if (p_rx == P0_16 || p_rx == P2_1 || p_rx == P3_17) {
      _uart = (LPC_UART_TypeDef*)LPC_UART1;
      NVIC_SetPriority(UART1_IRQn, 1);
    } else
    if (p_rx == P0_11 || p_rx == P2_9 || p_rx == P4_23) {
      _uart = LPC_UART2;
      NVIC_SetPriority(UART2_IRQn, 1);
    }
#elif defined(TARGET_LPC11UXX)
    if (p_rx == p10) {
      _uart = LPC_USART;
      NVIC_SetPriority(UART_IRQn, 1);
    }
#elif defined(TARGET_LPC11XX)
    // LPC1114 support by Stanly Chen
    if (p_rx == P1_6) {
      _uart = (LPC_UART_TypeDef*)UART_0;
      NVIC_SetPriority(UART_IRQn, 1);
    }
#endif

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

//    timeout01.attach_us(this, &DMX::int_timer, DMX_TIME_BETWEEN);
}

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

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

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

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

void DMX::int_timer () {

    switch (mode_tx) {
    case DMX_MODE_BEGIN:
        // Break Time
        timeout01.detach();
#ifdef RDM_ENABLE
        if (mode_rdm && _xmit) _xmit->write(XMIT_TX);
#endif
        _uart->LCR |= (1 << 6);
        mode_tx = DMX_MODE_BREAK;
        timeout01.attach_us(this, &DMX::int_timer, 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, time_mab);
        break;

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

void DMX::int_tx () {
    // Data
    if (mode_tx == DMX_MODE_DATA) {
#ifdef RDM_ENABLE
        if (mode_rdm && addr_tx < data_rdm[1] + 1) {
            // RDM data
            _dmx.putc(data_rdm[addr_tx]);
            addr_tx ++;
        } else
        if (!mode_rdm && addr_tx < DMX_SIZE) {
#else
        if (addr_tx < DMX_SIZE) {
#endif // RDM_ENABLE
            // DMX data
#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); // disable
            mode_tx = DMX_MODE_BEGIN;
            is_sent = 1;
#ifdef RDM_ENABLE
            if (mode_rdm) {
                if (_xmit) _xmit->write(XMIT_RX);
                mode_rdm = 0;
                mode_tx = DMX_MODE_STOP;
            } else {
                timeout01.attach_us(this, &DMX::int_timer, time_mbb);
            }
#else
            timeout01.attach_us(this, &DMX::int_timer, time_mbb);
#endif // RDM_ENABLE
        }
    }
}

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 (is_rdm_received) {
            return;
        } else
        if (addr_rx >= 24 && mode_rx == DMX_MODE_DATA) {
            is_received = 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;
#ifdef RDM_ENABLE
        } else
        if (dat == RDM_START_CODE) {
            addr_rx = 0;
            mode_rx = DMX_MODE_RDM;
#endif
        } else {
            mode_rx = DMX_MODE_ERROR;
        }

    } else
    if (mode_rx == DMX_MODE_DATA) {

        // Data
        data_rx[addr_rx] = dat;
        addr_rx ++;

        if (addr_rx >= DMX_SIZE) {
            is_received = 1;
            mode_rx = DMX_MODE_BEGIN;
        }

#ifdef RDM_ENABLE
    } else
    if (mode_rx == DMX_MODE_RDM) {

        // Rdm
        data_rx[addr_rx] = dat;
        addr_rx ++;

        if (addr_rx >= 2 && addr_rx >= data_rx[1] + 1) {
            is_rdm_received = 1;
            mode_rx = DMX_MODE_BEGIN;
        } else
        if (addr_rx >= sizeof(data_rdm)) {
            mode_rx = DMX_MODE_ERROR;
        }
#endif
    }
}

void DMX::start () {
    if (mode_tx == DMX_MODE_STOP) {
#ifdef RDM_ENABLE
        if (_xmit) _xmit->write(XMIT_TX);
#endif
        mode_tx = DMX_MODE_BEGIN;
        is_sent = 0;
        timeout01.attach_us(this, &DMX::int_timer, time_mbb);
    }
}

void DMX::stop () {
    _dmx.attach(0, Serial::TxIrq);
    timeout01.detach();
    mode_tx = DMX_MODE_STOP;
#ifdef RDM_ENABLE
    if (_xmit) _xmit->write(XMIT_RX);
#endif
}

void DMX::clear () {
    int i;

    for (i = 0; i < DMX_SIZE; i ++) {
        data_tx[i] = 0;
        data_rx[i] = 0;
    }
}

int DMX::isReceived (){
    int r = is_received;
    is_received = 0;
    return r;
}

int DMX::isSent () {
    int r = is_sent;
    is_sent = 0;
    return r;
}

unsigned char *DMX::getRxBuffer () {
    return data_rx;
}

unsigned char *DMX::getTxBuffer () {
    return data_tx;
}

int DMX::setTimingParameters (int breaktime, int mab, int mbb) {
    if (breaktime < 88 || breaktime > 1000000) return -1;
    if (mab < 8 || mab > 1000000) return -1;
    if (mbb < 0 || mbb > 1000000) return -1;

    time_break = breaktime;
    time_mab   = mab;
    time_mbb   = mbb;
    return 0;
}