Jump to content
  • 0

Precision Timing for TM1803 LED Strip via MPLAB


Chris I

Question

I am at my wits end and hope someone more literate than I will help.

In short I had a MPLABX cx32 v1.0 project to target an uno32 board to operate a radioshack tricolor LED p/n 2760249 and it worked PERFECTLY using core timer for precision timing.

However, even after manually installed Microchip's peripheral library  on top of xc32 x1.34 and genning the SystemConfig function to complile.  the core timer counts are producing erratic results...no matter what I put in blocking whiles for CP0 counts I cant make the pattern....waiting X counts while high is different than while low.

This LED strip works on 24 bits...

a LOGIC one needs to be ~1.5us HIGH followed by .78us LOW

a LOGIC zero needs to be .78us HIGH followed by 1.5us LOW

in the code below i an sending 0xFF00FF....so 8 ones followed by 8 zeros followed by 8 ones with timing above.

To do that I was using core timer counts...for now I just want something that simple w/o interrupts.

Used to be a core timer counts was 25ns like clockwork.  That was several years ago and now that I have installed the new versions of the toolchain something is a amiss.

I am including my complete code and a screen shot of a scope plot or 2 showing weird timing.

#include <xc.h>
#include <cp0defs.h>
#include <sys/attribs.h>
#include <p32xxxx.h>
#include <plib.h>

#pragma config FPLLIDIV = DIV_2         // PLL Input Divider (2x Divider)
#pragma config FPLLMUL = MUL_20         // PLL Multiplier (20x Multiplier)
#pragma config FPLLODIV = DIV_1         // System PLL Output Clock Divider (PLL Divide by 1)

#pragma config FNOSC = PRIPLL           // Oscillator Selection Bits (Primary Osc w/PLL (XT+,HS+,EC+PLL))
#pragma config FSOSCEN = OFF             // Secondary Oscillator Enable (Enabled)
#pragma config IESO = ON                // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = XT             // Primary Oscillator Configuration (XT osc mode)
#pragma config FWDTEN = OFF              // Watchdog Timer Enable (WDT Enabled)

#define SYS_CLOCK    (80000000L)
#define SYS_FREQ    (80000000L)

UINT64 start=0;
UINT64 stop=0;

const unsigned long pattern_test_rainbow[10][10]={
  {0xff0000,0xff7f00,0xffff00,0x00ff00,0x0000ff,0x6f00ff,0x8f00ff,0x000000,0x000000,0x000000},
  {0x000000,0xff0000,0xff7f00,0xffff00,0x00ff00,0x0000ff,0x6f00ff,0x8f00ff,0x000000,0x000000},
  {0x000000,0x000000,0xff0000,0xff7f00,0xffff00,0x00ff00,0x0000ff,0x6f00ff,0x8f00ff,0x000000},
  {0x000000,0x000000,0x000000,0xff0000,0xff7f00,0xffff00,0x00ff00,0x0000ff,0x6f00ff,0x8f00ff},
  {0x8f00ff,0x000000,0x000000,0x000000,0xff0000,0xff7f00,0xffff00,0x00ff00,0x0000ff,0x6f00ff},
  {0x6f00ff,0x8f00ff,0x000000,0x000000,0x000000,0xff0000,0xff7f00,0xffff00,0x00ff00,0x0000ff},
  {0x0000ff,0x6f00ff,0x8f00ff,0x000000,0x000000,0x000000,0xff0000,0xff7f00,0xffff00,0x00ff00},
  {0x00ff00,0x0000ff,0x6f00ff,0x8f00ff,0x000000,0x000000,0x000000,0xff0000,0xff7f00,0xffff00},
  {0xffff00,0x00ff00,0x0000ff,0x6f00ff,0x8f00ff,0x000000,0x000000,0x000000,0xff0000,0xff7f00},
  {0xff7f00,0xffff00,0x00ff00,0x0000ff,0x6f00ff,0x8f00ff,0x000000,0x000000,0x000000,0xff0000},
};

 int main(int argc, char** argv) {
SYSTEMConfigPerformance(80000000); 
//SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
TRISF = 0x0000;
PORTF = 0x0000;

send_strip(0xff00ff);

while(1)
    {
   
   }
    return (EXIT_SUCCESS);
}

void send_strip(unsigned int data)
{
  int i;
  unsigned long long j=0x800000;
  for (i=0;i<24;i++)
  {
    if (data & j)
    {
       PORTFbits.RF1=1;
       start=_CP0_GET_COUNT() ;
       while(_CP0_GET_COUNT()<=(start+36));   //40MHz=> period is  25ns...neded this to be 1.55us 
        PORTFbits.RF1=0;
        start=_CP0_GET_COUNT() ;
        while(_CP0_GET_COUNT()<=(start));
    }
    else
    {
       PORTFbits.RF1=1;
        start=_CP0_GET_COUNT() ;
        while(_CP0_GET_COUNT()<=(start));
         PORTFbits.RF1=0;
        start=_CP0_GET_COUNT() ;
        while(_CP0_GET_COUNT()<=(start+36));
    }
    j>>=1;
  }
}
void set_white()
{
//    INTDisableInterrupts();
    int i;
    for (i=0;i<10;i++)
    {
        send_strip(0x00ffff);
    }
  //  INTEnableInterrupts();
        PORTFbits.RF1=0;
        start=_CP0_GET_COUNT() ;
        while(_CP0_GET_COUNT()<=(start+1000));
  }

void send_1M_pattern(const unsigned long data[][10], int pattern_no, int frame_rate)
{
  int i=0;
  int j=0;
  UINT32 temp_data;
  INTDisableInterrupts();
  for (i=0;i<pattern_no;i++)
  {
  
    for (j=0;j<10;j++)
    {
      temp_data=&data[j];
      send_strip(temp_data);
    }
    INTEnableInterrupts();

    start=_CP0_GET_COUNT() ;
        while(_CP0_GET_COUNT()<=(start+frame_rate*20000000));

  }
}

 

ScopePlots.docx

Link to comment
Share on other sites

1 answer to this question

Recommended Posts

 

 

Hi chris,

I'm not sure why you are having one part of the if else at 1.5us and the other at 458us using the _CP0_GET_COUNT() function but i would use the debugger in MPLABX and step into the send_strip function and see what is going on. I believe the 1.55 us would be start+38 and the .78us would be start+31 as shown below in the function. Here is a library for mpide that uses the uno32 and 24bit neopixels that might help. I know that they ended up using assemply with no-op's to get the timing down. Hope this helps!

cheers,

Jon

 

 

void send_strip(unsigned int data)
{
  int i;
  unsigned long long j=0x800000;
  for (i=0;i<24;i++)
  {
    if (data & j)
    {

        PORTFbits.RF1=1;
       start=_CP0_GET_COUNT() ;
       while(_CP0_GET_COUNT()<=(start+38));   //40MHz=> period is  25ns...neded this to be 1.55us 
        PORTFbits.RF1=0;
        start=_CP0_GET_COUNT() ;
        while(_CP0_GET_COUNT()<=(start+31));
    }
    else
    {
       PORTFbits.RF1=1;
        start=_CP0_GET_COUNT() ;
        while(_CP0_GET_COUNT()<=(start+31));
         PORTFbits.RF1=0;
        start=_CP0_GET_COUNT() ;
        while(_CP0_GET_COUNT()<=(start+38));

   }

 

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...