CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

WS2811 RGB lamp IC in High speed mode

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
horizontechno



Joined: 07 Oct 2011
Posts: 8

View user's profile Send private message Send e-mail Visit poster's website

WS2811 RGB lamp IC in High speed mode
PostPosted: Sun Feb 17, 2013 8:22 pm     Reply with quote

Hello

I try to control led 50x50 RGB with WS2811 IC inside
with PIC 18F26K22 in 64mhz.

My code working, but got some random flickering !!

I need help to make more faster code to send data to the lamp.
This is my SPI setup:
Code:
setup_spi2( SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16 );


and my code to send SPI 12Bit to the lamp
Code:

void xneth(){
 
int a1;
int a2;
int a3;
int a4;
int16 nq;
int buf;

for(nq=0;nq<512;nq++){
     buf=DMX[nq];

a1=0b10001000;

if (bit_test(buf,7)) {
bit_set(a1,5);
bit_set(a1,6);
}
if (bit_test(buf,6)) {
bit_set(a1,1);
bit_set(a1,2);
}
spi_write2(a1); // 10


a2=0b10001000;
if (bit_test(buf,5)) {
bit_set(a2,5);
bit_set(a2,6);
}
if (bit_test(buf,4)) {
bit_set(a2,1);
bit_set(a2,2);
}
spi_write2(a2); // 10
 
 
a3=0b10001000;
if (bit_test(buf,3)) {
bit_set(a3,5);
bit_set(a3,6);
}
if (bit_test(buf,2)) {
bit_set(a3,1);
bit_set(a3,2);
}
 spi_write2(a3); // 10
 
a4=0b10001000;
if (bit_test(buf,1)) {
bit_set(a4,1);
bit_set(a4,2);
}
 
if (bit_test(buf,0)) {
bit_set(a4,5);
bit_set(a4,6);
}

spi_write2(a4); // 10

}

delay_us(50);

}

Question
Ttelmah



Joined: 11 Mar 2010
Posts: 19334

View user's profile Send private message

PostPosted: Mon Feb 18, 2013 3:37 am     Reply with quote

Your indenting is foul.....

However, you can save a little time, by not using the CCS functions here. Preparing the next byte 'while' the first is sending. So:
Code:

#byte ssp2buff=getenv("SFR:SSP2BUF")
#byte ssp2stat=getenv("SFR:SSP2STAT")
#bit ssp2_has_data=ssp2stat.1
#define SPI2_PUT(x) spi2_buff=x
//clear the sspbuffer
void ssp2_clear_buff(void) {
   int8 dummy;
   dummy=ssp2buff;
}

//wait for SSP to complete a transfer
void wait_for_ssp2(void) {
   while(!ssp2_has_data);
   ssp2_clear_buff; //you must clear the buffer or overflow will trigger
}

void xneth(void) {
   int a1; //why use more than one variable?
   int16 nq;
   int buf;

   for(nq=0;nq<512;nq++){
      buf=DMX[nq];

      //combine loading the value with the first test.
      if (bit_test(buf,7))
         a1=0b11101000;
      else
         a1=0b10001000;

     if (bit_test(buf,6)) {
         bit_set(a1,1);
         bit_set(a1,2);
     }
     wait_for_ssp2();
     SPI2_PUT(a1); // 10 Now the byte is being sent, get the next ready

     if (bit_test(buf,5))
         a1=0b11101000;
     else
         a1=0b10001000;
 
     if (bit_test(buf,4)) {
         bit_set(a1,1);
         bit_set(a1,2);
     }
     wait_for_ssp2(); //wait for the last transmission to complete
     SPI2_PUT(a1); // 10
//etc..

What this does that is different, is just loading the hardware buffer, and then _while the SPI is sending_, gets the next value ready. Instead of waiting for the transmission to complete before proceeding. Obviously it then must wait for the transmission to complete before loading this to send.
It saves a few uSec as well, by combining the first test and loading the value to send. Saves a few bytes of RAM by just using one variable. This requires the ssp to already be setup, and enabled. You may need to set the SSPEN bit yourself. Doing this will get rid of the delays between the bytes, tightening the timings.

If I remember correctly, these chips don't use SPI as such, but a continuous clock 'stream', with varying pulse widths for 1/0. so what you are doing is generating this by using multiple bits in the SPI (Fairly sure I suggested this some time ago to another poster asking about driving something similar....). Now the stream rate is meant to be 400KHz (optionally 800kHz). You are using each half of the SPI byte, as one clock. So four SPI bits=one cycle for the LED. Now with your clock selection, 64MHz/4/16 per SPI bit. So your SPI is clocking at 1MHz. This then gives you effectively 250KHz to the chip. Not the right rate. You need to switch to using the Timer2 option to control the SPI. Up the SPI rate to 1.6MHz (SPI_CLK_T2 & setup_timer_2(T2_DIV_BY_1,9,16);). Then you will be clocking the units at the right speed. Or use setup_timer_2(T2_DIV_BY_1,5,16) which will run the unit in high speed mode (800KHz clock rate).

Best Wishes
horizontechno



Joined: 07 Oct 2011
Posts: 8

View user's profile Send private message Send e-mail Visit poster's website

More help
PostPosted: Mon Feb 18, 2013 8:10 pm     Reply with quote

Hello Ttelmah

Thank you for your fast reply !!

I have try to change the SPI setup to Timer 2 as your email
Code:
setup_timer_2(T2_DIV_BY_1,5,16); // for 800khz

but with this setup i got .9us bit rate ? for the 800Khz i need .250us bit rate ?

Can you help me to get the right value for the 800Khz ?

Thanks for your time

Alain
Ttelmah



Joined: 11 Mar 2010
Posts: 19334

View user's profile Send private message

PostPosted: Tue Feb 19, 2013 1:45 am     Reply with quote

For 800KHz, you want an SPI bit time of:

(1/800000)/4 = 0.3125uSec

This then gives a 'simulated' bit time of 0.3125*4 = 1.25uSec. Using four SPI bits for each of the simulated bits.

So your SPI clock needs to be 3.2MHz.

I'd forgotten on these chips, the Timer2 output is divided by two (on some of the 16bit PIC's it isn't). So currently you'd be getting:

64E6/4/6/2 = 1.3MHz, and a bit time of 0.75uSec (not 0.9.....).

You won't quite be able to get the right rate. Nearest would be using 1 or two on the divider, giving /2 or /3 of the peripheral clock, and 2.6MHz, or 4MHz. Using 4MHz, would give 1MHz simulated clock, while 2.6MHz would give 650K.

Unfortunately, from your current master clock, the 'right rate', is not quite doable. Go to 51.2MHz master clock, and it can be done, using the standard divisor, or the timer2 route.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group