0

I have a DAC8562 by analog devices. Here is a data sheet:

http://www.analog.com/media/en/technical-documentation/data-sheets/DAC8562.pdf

It is a parallel 12-bit DAC. I have a function written in C which controls GPIO pins to latch an input value to the DAC. My problem is that my function is rather slow. Here is the code:

void setOut(uint16_t data) {

//Set DATA
if (data & 0x01) {
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN2);
} else {
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN2);
}
if (data & 0x02) {
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN0);
} else {
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN0);
}
if (data & 0x04) {
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN1);
} else {
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN1);
}
if (data & 0x08) {
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN7);
} else {
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN7);
}
if (data & 0x10) {
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN6);
} else {
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN6);
}
if (data & 0x20) {
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN4);
} else {
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN4);
}
if (data & 0x40) {
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P5, GPIO_PIN6);
} else {
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN6);
}
if (data & 0x80) {
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN6);
} else {
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN6);
}
if (data & 0x100) {
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P6, GPIO_PIN7);
} else {
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN7);
}
if (data & 0x200) {
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN3);
} else {
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN3);
}
if (data & 0x400) {
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P5, GPIO_PIN1);
} else {
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN1);
}
if (data & 0x800) {
    MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN5);
} else {
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN5);
}

// Set CE Low
MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN4);

// Set CE High
MAP_GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN4);}

The problem is the layout of the board requires the specific port/pin assignments I am using. As of now I am checking each bit individually and matching the output of the pin that bit represents as high or low. Is there a more efficient way of doing this?

Additional Info: I am using and MSP432P401R for a micro controller. I am using TI's driver library to control GPIO.

5
  • That's why one should put some thought into designing the hardware, too. Change the wiring to a more intelligent one. Commented Feb 17, 2016 at 0:31
  • 1
    @Olaf Your comment is pretty useless as I already addressed the layout is out of my control. Commented Feb 17, 2016 at 0:32
  • No, you did not. Still but-kicking the hardware designer at least gives some satisfaction. There hardly is an efficient way to make the code much better, even more as the signals are not just mixed on a single port, but over multiple. What did they do, roll a dice for the pinout? Even a lookup table is hardly usable - even iff you can spare 8KiB Flash. Commented Feb 17, 2016 at 0:37
  • 1
    @Olaf from the original post "The problem is the layout of the board requires the specific port/pin assignments I am using." The layout makes the pin assignments nice for a breakout board off the launchpad. Why TI decided to arrange the launchpad pins the way they did I will never know. Thank you for your comments I didn't think there was anything better I will have to make due with what I have Commented Feb 17, 2016 at 0:46
  • What do you expect? You can either straighten the pinout or have to live with crappy&overhead software. That's why I don't like evaluation boards. Commented Feb 17, 2016 at 0:51

2 Answers 2

1

Better code smart ! Here you have:

Solution 1:

struct param_t
{
  uint8_t bitmask;
  uint??_t gpio_port;
  uint??_t gpio_pin;
}

const param_t param[XXXX] = 
{
  {0x01, GPIO_PORT_P4, GPIO_PIN2},
  {0x02, GPIO_PORT_P4, GPIO_PIN0},
  {...},
}

void setOut(uint16_t data)
{
  for(int i=0; i<XXXX; i++)
  {
    if(data & param[i].bitmask)
    {
      MAP_GPIO_setOutputHighOnPin(param[i].gpio_port, param[i].gpio_pin)
    }
    else
    {
      MAP_GPIO_setOutputLowOnPin(param[i].gpio_port, param[i].gpio_pin)
    }
  }
}

Solution 2:

const callback_t callback[2] =
{
  MAP_GPIO_setOutputHighOnPin,
  MAP_GPIO_setOutputLowOnPin
}

void setOut(uint16_t data)
{
  callback[(int)(data & 0x01 == 0)](GPIO_PORT_P4, GPIO_PIN2};
  callback[(int)(data & 0x02 == 0)](GPIO_PORT_P4, GPIO_PIN0};
  ...
}

Solution 3: (Not sure it is possible)

After that i suppose that MAP_GPIO_setOutputXxxxOnPin is slow. It read modify then write back the register. Instead of multiple call to that function on the same port you should read it once, modify all its pin locally in the memory and then write it back once.

Sign up to request clarification or add additional context in comments.

3 Comments

Maybe this is not what you want ... if speed is what you want. tell me if so, i will delete my post
I added another solution to avoid if/else statement. Note sure if it is faster but it may help.
Second solution did not work. (int)(data & 0x02) equal to 2 (or zero, sure!).
0

Ooo, there is a lot of room for optimization!

  1. Replace this ugly MAP_GPIO_setOutputXXX () with fast raw register write:

    include "msp432.h" // it is from TI DriverLib too
    ...
    if (data & 0x01)
        P4OUT |= (1<<2);
    else
        P4OUT &= ~(1<<2);
    // and so on ...
    
  2. Instead of bitwise operations, use Cortex's core feature bit banding:

    // Convert SRAM address
    #define BITBAND_SRAM_REF 0x20000000
    #define BITBAND_SRAM_BASE 0x22000000
    #define BITBAND_SRAM(a,b) HWREG32((BITBAND_SRAM_BASE + (&(a) - BITBAND_SRAM_REF)*32 + (b*4))) 
    
    // Convert PERI address
    #define BITBAND_PERI_REF 0x40000000
    #define BITBAND_PERI_BASE 0x42000000
    #define BITBAND_PERI(a,b) HWREG32((BITBAND_PERI_BASE + (&(a) - BITBAND_PERI_REF)*32 + (b*4)))
    
    ...
    if (data & 0x01)
        BITBAND_PERI (P4OUT, 2) = 1;
    else
        BITBAND_PERI (P4OUT, 2) = 0;
    ...
    
  3. Modify bitband method, to remove if() statements. This is possible, because for bit band wrote only least significant bit is matter.

    BITBAND_PERI (P4OUT, 2) = data >> 0;  // bit 0
    BITBAND_PERI (P4OUT, 0) = data >> 1;  // bit 1
    BITBAND_PERI (P6OUT, 1) = data >> 2;  // bit 2
    BITBAND_PERI (P2OUT, 7) = data >> 3;  // bit 3
    // etc
    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.