Porting library to Arduino Due - Accessing USART registers

Hi everyone!

I am working on porting the Conceptinetics DMX library to Arduino Due.
The library uses the USART/serial to pass data to a DMX shield.

My problem is that the USART commands are specifically written for AVR chips and the compiler generates errors related to the manipulation of USART control registers on Due.

Look at the #define of the library:

/*
  Conceptinetics.cpp - DMX library for Arduino
  Copyright (c) 2013 W.A. van der Meeren <danny@illogic.nl>.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 3 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

/*
  This code has been tested using the following hardware:

  - Arduino UNO R3 using a CTC-DRA-13-1 ISOLATED DMX-RDM SHIELD 
  - Arduino MEGA2560 R3 using a CTC-DRA-13-1 ISOLATED DMX-RDM SHIELD 
*/


#include "pins_arduino.h"
#include "Conceptinetics.h"

#include <inttypes.h>
#include <stdlib.h>

#include <avr/interrupt.h>
#include <avr/io.h>

#include <util/delay.h>


#if defined (USE_DMX_SERIAL_0)

    #if defined (USART__TXC_vect)
      #define USART_TX USART__TXC_vect
    #elif defined(USART_TX_vect)
      #define USART_TX  USART_TX_vect
    #elif defined(USART0_TX_vect)
      #define USART_TX USART0_TX_vect
    #endif 

    #if defined (USART__RXC_vect)
      #define USART_RX USART__RXC_vect
    #elif defined(USART_RX_vect)
      #define USART_RX  USART_RX_vect
    #elif defined(USART0_RX_vect)
      #define USART_RX USART0_RX_vect
    #endif 

    #if defined UDR
      #define DMX_UDR UDR
    #elif defined UDR0
      #define DMX_UDR UDR0
    #endif

    #if defined(UBRRH) && defined(UBRRL)
      #define DMX_UBRRH UBRRH
      #define DMX_UBRRL UBRRL
    #elif defined(UBRR0H) && defined(UBRR0L)
      #define DMX_UBRRH UBRR0H
      #define DMX_UBRRL UBRR0L
    #endif

    #if defined(UCSRA)
      #define DMX_UCSRA UCSRA
    #elif defined(UCSR0A)
      #define DMX_UCSRA UCSR0A
    #endif

    #if defined(UCSRB)
       #define DMX_UCSRB UCSRB
    #elif defined (UCSR0B)
       #define DMX_UCSRB UCSR0B
    #endif

    #if defined(TXEN) && defined(TXCIE)
        #define DMX_TXEN TXEN
        #define DMX_TXCIE TXCIE
    #elif defined(TXEN0) && defined(TXCIE0)
        #define DMX_TXEN TXEN0
        #define DMX_TXCIE TXCIE0
    #endif

    #if defined(RXEN) && defined(RXCIE)
        #define DMX_RXEN RXEN
        #define DMX_RXCIE RXCIE
    #elif defined(RXEN0) && defined(RXCIE0)
        #define DMX_RXEN RXEN0
        #define DMX_RXCIE RXCIE0
    #endif

    #if defined(FE)
      #define DMX_FE FE
    #elif defined(FE0)
      #define DMX_FE FE0
    #endif

    #define RX_PIN 0
    #define TX_PIN 1

#elif defined (USE_DMX_SERIAL_1)
    #define USART_RX USART1_RX_vect
    #define USART_TX USART1_TX_vect
    #define DMX_UDR UDR1
    #define DMX_UBRRH UBRR1H
    #define DMX_UBRRL UBRR1L
    #define DMX_UCSRA UCSR1A
    #define DMX_UCSRB UCSR1B
    #define DMX_TXEN TXEN1
    #define DMX_TXCIE TXCIE1
    #define DMX_RXEN RXEN1
    #define DMX_RXCIE RXCIE1
    #define DMX_FE FE1
    #define RX_PIN 19
    #define TX_PIN 18
#elif defined (USE_DMX_SERIAL_2)
    #define USART_RX USART2_RX_vect
    #define USART_TX USART2_TX_vect
    #define DMX_UDR UDR2
    #define DMX_UBRRH UBRR2H
    #define DMX_UBRRL UBRR2L
    #define DMX_UCSRA UCSR2A
    #define DMX_UCSRB UCSR2B
    #define DMX_TXEN TXEN2
    #define DMX_TXCIE TXCIE2
    #define DMX_RXEN RXEN2
    #define DMX_RXCIE RXCIE2
    #define DMX_FE FE2
    #define RX_PIN 17
    #define TX_PIN 16
#elif defined (USE_DMX_SERIAL_3)
    #define USART_RX USART3_RX_vect
    #define USART_TX USART3_TX_vect
    #define DMX_UDR UDR3
    #define DMX_UBRRH UBRR3H
    #define DMX_UBRRL UBRR3L
    #define DMX_UCSRA UCSR3A
    #define DMX_UCSRB UCSR3B
    #define DMX_TXEN TXEN3
    #define DMX_TXCIE TXCIE3
    #define DMX_RXEN RXEN3
    #define DMX_RXCIE RXCIE3
    #define DMX_FE FE3
    #define RX_PIN 14
    #define TX_PIN 15
#endif


#define LOWBYTE(v)   ((uint8_t) (v))
#define HIGHBYTE(v)  ((uint8_t) (((uint16_t) (v)) >> 8))

#define BSWAP_16(x)  ( (uint8_t)((x) >> 8) | ((uint8_t)(x)) << 8 )

Initially, there is a problem with definitions. Due requires a different set of definitions surrounding the USART registers, which do not qualitatively match the AVR definitions.

Looking at the arduino due (Due) and mega (Mega) data sheets, we can see that the library uses pre-defined bit-index numbers to manipulate the 8-bit AVR registers. Example in pseudo code: register |= (1<<bitIndexNumber)

Arduino Due uses a different system to manipulate registers. The pre-defined numbers are not index numbers but numerical values. For example, on Mega and Uno we would write UCSR0B |= (1<<TXEN0); where TXEN0 is 3, the bit index number of TX enable on the register. On Due, the similar #define related to the register does not define the index number but the actual value (ex US_CR_TXEN is already equal to 1<<TXEN).

Is a command like UCSR0B |= (1<<TXEN0)
rewritten as usart->US_CR = US_CR_TXEN; on the Due?

I get “usart” not defined in this scope
and “US_CR” not defined in this scope errors when trying to compile this code.
How is this code successfully implemented in the usart.c file? (github usart.c link)

Where are these defined (ex US_CR, usart, US_IER)? I know that for example US_CR_TXEN is defined in the component_usart.h file but I get an error for the definition of US_CR alone. Why are these errors generated since all usart-related libraries are included?

Also, what does the number behind the register name (ex UCSR0B) represent in AVR?

More generally, how do I access the USART registers on Due? Moreover, how do I select which of Due’s USARTs to use? (USART 0-3)

Information on the use of USART registers for DMX: A Arduino Library for sending and receiving DMX

Please excuse my poor knowledge of technical terms or any silly mistakes since I am a beginner in microelectronics.

Thanks for any help :slight_smile:

Conceptinetics.h (11.6 KB)

Conceptinetics.cpp (34.8 KB)

usart.c (11.9 KB)