An initial port to the FRDM-K46Z based on the the following: https://developer.mbed.org/users/okini3939/notebook/dmx512/

Dependents:   FRDM-Dowser

Fork of DMX by Suga koubou

Need to update the UART references to the K46Z. The KE02 Sub-Family Reference Manual provides us with the required information.

The modifications are wrapped with the target for the K46: For example, defined(TARGET_KL46Z)

DMX.cpp

Committer:
rosienej
Date:
2015-03-27
Revision:
21:59c200304b47
Parent:
20:b1942f266f49

File content as of revision 21:59c200304b47:

/*
 * 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"

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

    clear();
//    mode_tx = DMX_MODE_BEGIN;
    mode_tx = DMX_MODE_STOP;
    mode_rx = DMX_MODE_BEGIN;
    is_recived = 0;
    is_sent = 0;

#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_KL46Z)
    /**
        Need to associate the _uart private variable with the user selected pin.
        Hook the interrupt pin.
    */
    if ((p_rx == PTE21) || (p_rx == PTA1)) {
        _uart = (UARTLP_Type *)UART0;
        NVIC_SetPriority(UART0_IRQn, 1);
    } else if (p_rx == PTE1) {
        _uart = (UARTLP_Type *)UART1;
        NVIC_SetPriority(UART1_IRQn, 1);
    } else if ((p_rx == PTE23) || (p_rx == PTE17)) {
        _uart = (UARTLP_Type *)UART2;
        NVIC_SetPriority(UART2_IRQn, 1);
    }

#elif defined(TARGET_LPC4088)
    if (p_rx == p10) {
        _uart = LPC_UART3;
        NVIC_SetPriority(UART3_IRQn, 1);
    } else if (p_rx == p31) {
        _uart = (LPC_UART_TypeDef*)LPC_UART4;
        NVIC_SetPriority(UART4_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();
#if defined(TARGET_KL46Z)
            /// Chapter 31.2  of the Freescale KE02 Sub-Famely Reference
            /// UARTx_C2 page 553 enable the transmitter and reciever
            ///  Sending a break we write a one, then write a zero.....  This sets send break bit
            _uart->C2 |= UART_C2_SBK_MASK | UART_C2_TE_MASK | UART_C2_RE_MASK;
#else
            /// Bit 6 in the LCR enables the break signal.....
            _uart->LCR |= (1 << 6);
#endif
            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();
#if defined(TARGET_KL46Z)
            /// This sets the break charcter to zero to send the break.
            _uart->C2 &= ~UART_C2_SBK_MASK;
#else
            _uart->LCR &= ~(1 << 6);
#endif
            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


#if defined(TARGET_KL46Z)
            /// Check the TDRE (Transmit Data Register Empty) flag... page 555
            /// The data is placed in D on the Freescale
            while(!(_uart->S1 & UART_S1_TDRE_MASK));
            _uart->D = DMX_START_CODE; // Freescale
#else
            /// Bit 5 of the LSR indicates the THR (Transmit Holding Register) is empty
            while(!(_uart->LSR & (1<<5)));
            _uart->THR = DMX_START_CODE;
#endif
#else
            _dmx.putc(DMX_START_CODE);
#endif
            break;
    }
}

void DMX::int_tx ()
{
    // Data
    if (mode_tx == DMX_MODE_DATA) {
        if (addr_tx < DMX_SIZE) {
#ifdef DMX_UART_DIRECT

#if defined(TARGET_KL46Z)
            _uart->D = (uint8_t)data_tx[addr_tx]; // Freescale
#else
            _uart->THR = (uint8_t)data_tx[addr_tx];
#endif
#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;
    int tmp1,tmp2;
#if defined(TARGET_KL46Z)
    /// looking for (7)erroneous data,(3) Framming Error, (4) Break
    tmp1 = (_uart->S1 & (UART_S1_NF_MASK|UART_S1_FE_MASK));         // NF,FE
    tmp2 = (_uart->S2 & UART_S2_LBKDIF_MASK);         //LBKDIF
    flg = (tmp1<<2) | tmp2;
#else
    flg = _uart->LSR;
#endif

#ifdef DMX_UART_DIRECT
#if defined(TARGET_KL46Z)
    dat = _uart->D;  // Freescale
#else
    dat = _uart->RBR;
#endif


#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 >= DMX_SIZE) {
            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 ()
{
    int i;

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