Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: Need guidance for software SPI with DMA (to drive TLC5947)

  1. #1
    Senior Member
    Join Date
    Sep 2015
    Location
    Taiwan, Asai. (Traditional Chinese)
    Posts
    165

    Need guidance for software SPI with DMA (to drive TLC5947)

    Hello community,
    I'm currently working on a pov project , using SD and TLC5947 as LED driver, on teensy 3.1
    the TLC5947 library I'm using is from adafruit : https://github.com/adafruit/Adafruit_TLC5947
    TLC5947 uses software SPI with clock, and 12bit for a single output channel, and follows by a clock signal each 12 bit data.
    the speed is not fast enough, and one way I came up with, is to read the next picture during displaying

    so I think I can rewrite the TLC5947 library with DMA.(another choice is the SD library, which seems to be much harder?)

    But there are only few DMA examples around the web, and I'm not yet used in C code yet, can't understand them well.
    I read through Paul's octows2812 library, it seems that the DMA uses three channel and controls a port at once,
    I still don't know how to use DMA with a single I/O or two.

    can anyone provide an example for arduino IDE
    like using pin 32 (PTB18) as data, and pin 25 (PTB19) as clock? pins could be modified,
    and from the examples, I would need to reserve a pin or few, to process DMA normally?
    thanks

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    11,981
    I did a bing search "pjrc spi dma" that hit on this 2014 thread that does dma inside transactions so I suppose it is current:

    DMA-SPI-and-SPI-transactions

    it has samples and more links and references to sample source.

  3. #3
    Senior Member
    Join Date
    Sep 2015
    Location
    Taiwan, Asai. (Traditional Chinese)
    Posts
    165
    thanks,
    start reading, hope i could came up with something to code tonight.
    ----
    and also, DMA channel seems to push byte for a unit, while TLC5947 takes 12 bit per clock.
    cutting the data would be possible choice for me now, but still are there other ways like configuring the DMA setting?
    from the POST i found it could be 1,2,4or8 byte, how about bits?
    Last edited by Po Ting; 01-05-2016 at 09:06 AM.

  4. #4
    Senior Member
    Join Date
    Sep 2015
    Location
    Taiwan, Asai. (Traditional Chinese)
    Posts
    165

    Lightbulb

    after days of studying , I finally have some understanding, but with many confuses and guessing
    please, can some DMA master help me

    from the OCTOws2811 library
    https://github.com/PaulStoffregen/Oc...S2811.cpp#L105
    #if defined(KINETISK)
    // pin 16 triggers DMA(port B) on rising edge (configure for pin 3's waveform)
    CORE_PIN16_CONFIG = PORT_PCR_IRQC(1)|PORT_PCR_MUX(3);
    pinMode(3, INPUT_PULLUP); // pin 3 no longer needed

    // pin 15 triggers DMA(port C) on falling edge of low duty waveform
    // pin 15 and 16 must be connected by the user: 16 is output, 15 is input
    pinMode(15, INPUT);
    CORE_PIN15_CONFIG = PORT_PCR_IRQC(2)|PORT_PCR_MUX(1);

    // pin 4 triggers DMA(port A) on falling edge of high duty waveform
    CORE_PIN4_CONFIG = PORT_PCR_IRQC(2)|PORT_PCR_MUX(3);
    Is the PORT_PCR_MUX() somekind of channel shared inside the MCU, to indicate PWM for DMA triggering?

    #if defined(KINETISK)
    // route the edge detect interrupts to trigger the 3 channels
    dma1.triggerAtHardwareEvent(DMAMUX_SOURCE_PORTB);
    dma2.triggerAtHardwareEvent(DMAMUX_SOURCE_PORTC);
    dma3.triggerAtHardwareEvent(DMAMUX_SOURCE_PORTA);
    // DMA channel #1 sets WS2811 high at the beginning of each cycle
    dma1.source(ones);
    dma1.destination(GPIOD_PSOR);
    dma1.transferSize(1);
    dma1.transferCount(bufsize);
    dma1.disableOnCompletion();

    // DMA channel #2 writes the pixel data at 20% of the cycle
    dma2.sourceBuffer((uint8_t *)frameBuffer, bufsize);
    dma2.destination(GPIOD_PDOR);
    dma2.transferSize(1);
    dma2.transferCount(bufsize);
    dma2.disableOnCompletion();

    // DMA channel #3 clear all the pins low at 48% of the cycle
    dma3.source(ones);
    dma3.destination(GPIOD_PCOR);
    dma3.transferSize(1);
    dma3.transferCount(bufsize);
    dma3.disableOnCompletion();
    dma3.interruptAtCompletion();

    #ifdef __MK20DX256__
    MCM_CR = MCM_CR_SRAMLAP(1) | MCM_CR_SRAMUAP(0);
    AXBS_PRS0 = 0x1032;
    #endif
    from the quote above, ones = 0xFF , and means to write all the ports to HIGH, or clear all.
    the data controlls ws2812 exists on DMA channel 2, with a source of "dma2.sourceBuffer((uint8_t *)frameBuffer, bufsize);"
    everytime the PWM edge it transfers a byte to GPIOD_PDOR,PCOR,PSOR, (which controls the eight LED strips)

    is the the DMA triggered for everybyte? since controll ws2812 requires timing bit-bang,
    and the dma2.sourceBuffer dumps a byte everycycle , I guess there was an internal counter or something, pointing the offset in the buffer?

    and also, how did DMA channel 3 know it's over, to call the ISR function?
    the ones is only a byte and thus it's used all over the data outputting,
    so is the end signal came from dma2.sourceBuffer() after all bytes were done?? won't it overflow??
    I didn't see, or I didn't recognize any other ending signal/register than
    dma3.interruptAtCompletion();
    and this interrupt, I guess, is triggered after all the data in buffer were dumped,
    but how did dma3 know the transfer were completed?

    and is the transfer only possible for bytes, and not bits?

    sadly my TLC5947 works with 12bit everychannel
    besides mathematics exchanging,
    that will also cause the DMAMEM buffer 8 times bigger(about 5KB for a single 36 pixel line), if I only use one pin for data

    or maybe I misunderstood something

    data also referenced from::
    https://www.pjrc.com/teensy/td_libs_OctoWS2811.html
    https://www.pjrc.com/teensy/K20P64M72SF1RM.pdf (warning! 1377pages)

    besides all the confuses, I came up with some ideas to work on

    since my project uses software SPI, TLC5947 works with a data line,every bit on data line would follow a clock raise/and lowered before next data,
    and finally followed with a latch signal,

    I could set up two channel with 1 data buffer, 3 DMA channels, 2 PWM timers? (one for data (PDOR), one for clocking(PSOR,PCOR)) and the ISR with a latch signal every 36*pixel clocks

    Oh, the TLC5947 drivers works at 20MHZ data transfer speed,
    the reason I need DMA is that I need to read the SD data, while showing pictures
    (typically a picture cycles for seconds, that gives plenty of time to read the next)

    if Paul's reading, can I modify your octows2811 library for TLD5947? if that technically possilbe.
    Thank you

    Thanks for all other reading,
    Last edited by Po Ting; 01-09-2016 at 02:09 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •