Jump to content

Recommended Posts

Using the FRAM as though it were RAM on the msp430fr59xx chips can make it really easy to drive those ws281x chips even at a relatively slow MCU clock rate. The ws281x chips are great because you can get a boat load of leds for the cost of only one pin. Also, it doesn't hurt the price of these ws281x chips keeps falling and making them more and more attractive.


I decided to see if I could take advantage of FRAM to help me drive some of those leds. I ended up with an extremely simple driver routine that works great even when you clock the FRAM MCU @ 6MHz. You couldn't really do this on a RAM limited msp430 chip as you would quickly run out of memory.


I configured the FRAM chip for 6MHz and then configured the SPI to use a clock divisor of 1
the MOSI is selected for output and is wired to ws281x DIN pin.

static const uint8_t frame_buffer[60*3*8] = {0}; /* provide an FRAM buffer for a strip of 60 leds */ 

 * inline msp430-elf-gcc asm version
void sendRGB(uint8_t * led_data, unsigned led_data_len) {
  const uint8_t *led_data_end = led_data+led_data_len;
  uint8_t *dest = const_cast<uint8_t *>(&frame_buffer[0]);
  uint8_t *frame = dest;

  do {
    unsigned color = *led_data++;
    register unsigned colormask = 0x80;

    do {
      *dest++ = (color & colormask) ? 0x78 : 0x60;
      colormask = colormask >> 1;
    } while (colormask);
  } while (led_data < led_data_end);

  // shift out bits in MSB order without much delay
  __asm__ __volatile__
      "  mov.b @%[led_data]+, %[TXBUF]    ; 5 cycles\n"
      "  jmp .+2                          ; 2 cycles\n"
      "  cmp %[led_data_end], %[led_data] ; 4 cycle\n"
      "  jl 1b                            ; 2 cycles\n"

      :[led_data] "+&r" (frame)
      ,[led_data_end] "+r" (dest)

      :[TXBUF] "m" (UCB0TXBUF)

      : "cc"
In the code above, I provided a function that expects an array of RGB data (well GRB data actually ) and I I looped through it and setup the FRAM buffer with proper SPI bits for ~333ns/~666ns and with a period of ~1500 ns. The wave it spews out looks really pretty on my scope. Best of all, the ws281x chips seem to like it.


I encountered one wierd anomaly of the eUSCI periperal. It seems that if the high bit of the last thing you sent is high, then the MOSI pin floats high instead of leaving the value at the last bit set. This is why I'm using 0x78 (0b01111000) and 0x60 (0b01100000) instead if 0xF0 and 0xC0. I wasted a bunch of time trying to find out why my code wasn't working on that one. I never did find a tech note or errata about it. If you are using the SPI device as a normal SPI device instead of a shift register, it wouldn't matter.



Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...