Jump to content
43oh

RGB to HSV Conversion with MSP430G2231 - Help!


Recommended Posts

Crash course pointers in C:

 

C only knows to types of things:

1) values

2) pointers

every variable you use is either of these types, most primitive types are called-by-value for example a character, an integer or a floating point number. Most other types are called-by-reference or pointers. The best known example of a pointer is the array.

An array is a pointer to a set of values (or other pointers), by using the square brackets you can select an indexed element in this set.

Would I want to access tha fourth integer in the array foo, I'd write foo[4]. By using the square brackets, without knowing I'm "dereferencing" the pointer called foo.

A pointer is basically a value that is equal to the address of the value in memory. This means that foo would be the address at which the first element of the array is stored. When writing foo[4] I tell C to take that address, add 4 integer sized memory blocks to that and take the value at that position.

Another way to dereference a pointer is using the asterisk in front of the variable name; this means that writing foo[0] is the same as writing *foo. Would I want to have the fourth element (which is index 3, as the first element is index 0), I could write foo[3] or *(foo + 3). Here you can more explicitly see that I add the number of element I want to skip over to the pointer and take the value at that location.

 

Now, this all sounds quite complicated, but it really isn't. It just takes some practice to figure out where and when to write an asterisk ( * ) or an ampersand ( & ). For the rest, try to ever realize wether your variable name denotes a value or a memory address.

// Pointer cheat sheet
int v; // v is an integer
int* p; // p is a pointer to an integer
p = &v; // take the address of v and assign that to p
*p = 6; // take the value where p is pointing to and assign 6 to it

// expect a integer value as first element, this value is a copy of the parameter supplied at the function call and this copy will no longer exist after this function ends
// expect a pointer to an integer as second element, this pointer is known as p in this function, although the pointer seizes to exist after the function ends, the address it was pointing to still exists
void func(int q, int* p)
{
*p = 6; // write the value 6 to the location p is pointing to
q = 6; // write 6 to the local variable q, this is of no use because the value is gone when the function ends
p = 6; // WRONG! let p point to address 6 in memory, unless you're really sure, you'll probably access memory you should not touch!
}

Sometimes you do alter the address a pointer is pointing to, for example in printing routines. Secretly, strings are arrays of characters. Which means you cannot supply a string to any function, just the location of the first character in it.

char* str = "hello";
print(str); // supply print with a pointer to the first character of "hello"
// The first character is str[0] or *str
// A string is always internally "terminated" by a '\0' character to tell C this is that last character.

void print(char* s)
{
while(*s != '\0') // is the value of the address s is pointing to equal to 0?
  serial.putch(*s++); // supply the value of the address s is pointing to to putch and then increment the pointer s by one element.
}

 

So what I'm doing in the HSV function is writing a value (255, or t) to the address r is pointing to. Also I must supply the address where r is kept to the function, so that's why I cannot pass leds[z], but must pass &leds[z] or leds + z. Since the latter is much more difficult to read, I suggest you stick to the first method of writing for now.

Link to post
Share on other sites
  • Replies 35
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

Crash course pointers in C:   C only knows to types of things: 1) values 2) pointers every variable you use is either of these types, most primitive types are called-by-value for example a charac

G2231 (2K flash) is a bad choice of chip for this. Try a G2553 (16K flash) or maybe G2452 (8K flash).   Sent from my C3PO via Tapatalk    

If this is your full code (what are you trying to do in bounce()?), you don't need a full-lfedged HSV2RGB function     for( hue = 0 ; hue < 360 ; hue ++) // this is where the problem lies!      

Cool, thanks for that.

Right I managed to run the program! Yeah!

But I'm almost having an epi because of all the flashing I'm getting, which I believe is the cause of the timer or interrupt, or a combination of both.

I'm gonna try and find the root of the problem, as well as a way to change the' saturation' and 'value' values more efficiently. Here's the code that I'm using for testing.

#include <msp430g2231.h>

// TLC inputs
#define SCLK_PIN	BIT5
#define MOSI_PIN	BIT7
#define GSCLK_PIN	BIT4
#define BLANK_PIN	BIT2
#define XLAT_PIN	BIT1
//#define DCPRG_PIN	BIT7 //P2
#define VPRG_PIN	BIT0

// 595 Inputs
#define DATA BIT6  // DS -> P2.6
#define LATCH BIT6 // ST_CP -> 1.6
#define CLOCK BIT7 // 11 -> 2.7

// --------------  MACROS ------------------------------------------//
#define setHigh(n)   ( P1OUT |= n )                   // Only for TLC!
#define setLow(n)   ( P1OUT &= ~n )                   // TLC!!
#define pulse(n)  do { setHigh(n); setLow(n); } while(0)
// ---------------------------------------------------------------------//

typedef unsigned char u_char;
typedef unsigned int u_int;
typedef unsigned short int us_int;
// Prototypes
void init(void);
void updateTLC();
void sendMOSI(u_int data);
void pulseClock ( void );
void pinWrite ( unsigned int, u_int );
void shiftOut(u_char);
void shift(unsigned int);
void delay (unsigned int);
void HSV2RGB(unsigned short int*, unsigned short int*, unsigned short int*, short int, unsigned char, unsigned char);

#define NUMBER_OF_LEDS 24
#define NUMBER_OF_COLUMNS 8
short int icount;

us_int leds[NUMBER_OF_LEDS];  // 0 - 7 Red Rows, 8 - 15 Green Rows, 16 - 23 Blue Rows {0, }
u_char timerCounter = 0;

void init(void)
{
	WDTCTL = WDTPW + WDTHOLD; // disable WDT
	DCOCTL |= DCO0 + DCO1; // DCO = 15.25MHz
	BCSCTL1 |= RSEL0 + RSEL1 + RSEL2 + RSEL3; // as above
	BCSCTL2 |= DIVS_3; // divide clock by 8

	P1OUT &= ~(VPRG_PIN + BLANK_PIN + XLAT_PIN + SCLK_PIN + MOSI_PIN );
	P1DIR |= VPRG_PIN + BLANK_PIN + XLAT_PIN + SCLK_PIN + MOSI_PIN;
	// 595
	P2SEL &= ~(CLOCK + LATCH);
	P1DIR |= DATA; 			// Setup pins as outputs
	P2DIR |= (CLOCK + LATCH);
	P1DIR |= GSCLK_PIN; 	// port 1.4 configured as SMCLK out
	P1SEL |= GSCLK_PIN;

	// setup timer
	CCR0 = 0xFFF;
	TACTL = TASSEL_2 + MC_1 + ID_0; // SMCLK, up mode, 1:1
	CCTL0 = CCIE; // CCR0 interrupt enabled
}


void main(void)
{
	init();
	updateTLC();

	pulse(XLAT_PIN);

	short int hue;
	unsigned char sat, val;
	int z;


	_bis_SR_register(GIE);

	for(;
	{
		for( hue = 0 ; hue < 360 ; hue++)
		{
			for( z = 0 ; z < 8 ; z++)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,255,255);
			}
			delay(400);
		}
		for ( hue = 359 ; hue >= 0 ; hue--)
		{
			for( z = 0 ; z < 8 ; z++)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,255,255);
			}
			delay(400);
		}
		_bis_SR_register(LPM0_bits);
	}
}

void updateTLC()
{
	u_char ledCounter = NUMBER_OF_LEDS >> 1;


	while (ledCounter-- > 0)
	{
		u_char i = ledCounter << 1;
		sendMOSI(leds[i + 1]);
		sendMOSI(leds[i]);
	}
}

void HSV2RGB(unsigned short int* r, unsigned short int* g, unsigned short int* b, short int h, unsigned char s, unsigned char v)
{
	unsigned char i, p, q, t;
	unsigned char fs;

	if (h < 60) i = 0;
	else if (h < 120) i = 1;
	else if (h < 180) i = 2;
	else if (h < 240) i = 3;
	else if (h < 300) i = 4;
	else if (h < 360) i = 5;
	else return;

	fs = ((h - i * 60) * s)/ 60;
	p = 255 - s;
	q = 255 - fs;
	t = 255 - s + fs;

	switch(i){
	case 0:
		*r = 255;
		*g = t;
		*b = p;
		break;
	case 1:
		*r = q;
		*g = 255;
		*b = p;
		break;
	case 2:
		*r = p;
		*g = 255;
		*b = t;
		break;
	case 3:
		*r = p;
		*g = q;
		*b = 255;
		break;
	case 4:
		*r = t;
		*g = p;
		*b = 255;
		break;
	case 5:
		*r = 255;
		*g = p;
		*b = q;
		break;
	}
	*r *= v;
	*g *= v;
	*b *= v;
}

void delay(unsigned int ms)
{
	while (ms--)
	{
		__delay_cycles(1000); // set for 16Mhz change it to 1000 for 1 Mhz
	}
}


#pragma vector = TIMER0_A0_VECTOR
		__interrupt void Timer_A0(void) {
			setHigh(BLANK_PIN);
			pulse(XLAT_PIN);
			setLow(BLANK_PIN);
			
			timerCounter++;
			if (timerCounter == 0x08) { // 0x08 - 2ms * 8 = 16.384ms, ~61Hz
				updateTLC();
				timerCounter = 0;
				_bic_SR_register_on_exit(LPM0_bits);
			}
		}

void sendMOSI(u_int mosi) {
	u_char c = 0;
	while (c < 12)
	{
		(mosi & 0x0800) ? (P1OUT |= MOSI_PIN) : (P1OUT &= ~MOSI_PIN);
		pulse(SCLK_PIN);
		mosi <<= 1;
		c++;
	}
}


void shiftOut(u_char val)
{

	P2OUT &= ~LATCH;
	pinWrite(DATA, val);// & (1 << i)));
	pulseClock();
	P2OUT |= LATCH;
	P2OUT &= ~LATCH;
}

void shift(unsigned int val)
{
	P2OUT &= ~LATCH;
	int i;
	for (i = 0; i < 8; i++)  {
		pinWrite(DATA, (val & (1 << i)));
		pulseClock();
	}
	P2OUT |= LATCH;
	P2OUT &= ~LATCH;
}

void pinWrite( unsigned int bit, u_int val )
{
	if (val){
		P1OUT |= bit;
	} else {
		P1OUT &= ~bit;
	}
}

// Pulse the clock pin
void pulseClock( void )
{
	P2OUT |= CLOCK;
	P2OUT ^= CLOCK;

}

Link to post
Share on other sites

You have this part in your main()

for(;
	{
		for( hue = 0 ; hue < 360 ; hue++)
		{
			for( z = 0 ; z < 8 ; z++)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,255,255);
			}
			delay(400);
		}
		for ( hue = 359 ; hue >= 0 ; hue--)
		{
			for( z = 0 ; z < 8 ; z++)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,255,255);
			}
			delay(400);
		}
		_bis_SR_register(LPM0_bits);
	}

You expect delay() to delay a number of milliseconds, which it doesn't because you upped your clock from 1MHz to 15.25MHz (says your comment in init()). So you'd have to __delay_cycles(15250) instead of __delay_cycles(1000).

Also, you go to LPM0 after you did a spin through the rainbow twice (RYGCBMMBCGYB), and with 360*2* 400/15.25 steps it should take 19 seconds before it reaches that point.

Link to post
Share on other sites

@ RobG - For every value of timercounter I put in, the program is still behaving erratically. It must be something to do with the main() but I can't see what.

if (timerCounter == 5B) { // 0x08 - 2ms * 8 = 16.384ms, ~61Hz
				updateTLC();
				timerCounter = 0;
				_bic_SR_register_on_exit(LPM0_bits);
			}

I changed it to a series of 'if' statements rather than 'for' loops in the hope that it would make a difference, but to no avail.

void main(void)
{
	init();
	updateTLC();

	pulse(XLAT_PIN);

	short int hue = 0;
	const unsigned char val =255, sat =255;
	int z;

	_bis_SR_register(GIE);

	for(;
	{
		allcolsON();   // just sets columns to +3.6V
		for( z = 0 ; z < 8 ; z++)
		{
			if (hue < 60)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,sat,val);
			}
			else if (hue < 120)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,sat,val);
			}
			else if (hue < 180)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,sat,val);
			}
			else if (hue < 240)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,sat,val);
			}
			else if (hue < 300)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,sat,val);
			}
			else if (hue < 360)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,sat,val);
			}
			else
			{
				hue=0;
			}
		}
		hue++;
		_bis_SR_register(LPM0_bits);
	}
}

void updateTLC()
{
	u_char ledCounter = NUMBER_OF_LEDS >> 1; //NUMBER_OF_LEDS


	while (ledCounter-- > 0)
	{
		u_char i = ledCounter << 1;
		sendMOSI(leds[i + 1]);
		sendMOSI(leds[i]);
	}
}

void HSV2RGB(unsigned short int* r, unsigned short int* g, unsigned short int* b, short int h, unsigned char s, unsigned char v)
{
	unsigned char i, p, q, t;
	unsigned char fs;

	if (h < 60) i = 0;
	else if (h < 120) i = 1;
	else if (h < 180) i = 2;
	else if (h < 240) i = 3;
	else if (h < 300) i = 4;
	else if (h < 360) i = 5;
	else return;

	fs = ((h - i * 60) * s)/ 60;
	p = 255 - s;
	q = 255 - fs;
	t = 255 - s + fs;

	switch(i){
	case 0:
		*r = 255;
		*g = t;
		*b = p;
		break;
	case 1:
		*r = q;
		*g = 255;
		*b = p;
		break;
	case 2:
		*r = p;
		*g = 255;
		*b = t;
		break;
	case 3:
		*r = p;
		*g = q;
		*b = 255;
		break;
	case 4:
		*r = t;
		*g = p;
		*b = 255;
		break;
	case 5:
		*r = 255;
		*g = p;
		*b = q;
		break;
	}
	*r *= v;
	*g *= v;
	*b *= v;
}

#pragma vector = TIMER0_A0_VECTOR
      __interrupt void Timer_A0(void) {

            static const int Cnt = 0x5B; // 0x08 when sat is 255

            setHigh(BLANK_PIN);
            pulse(XLAT_PIN);
            setLow(BLANK_PIN);
            timerCounter++;
            if (timerCounter == Cnt) { // 0x08 - 2ms * 8 = 16.384ms, ~61Hz
                updateTLC();
                timerCounter = 0;
                _bic_SR_register_on_exit(LPM0_bits);
            }
        }

I don't know where I'm going wrong :-(

Link to post
Share on other sites
        for(;
	{
		allcolsON();   // just sets columns to +3.6V
		for( z = 0 ; z < 8 ; z++)
		{
			if (hue < 60)
			{
			...
			}
		}
		hue++;
		_bis_SR_register(LPM0_bits);
	}

You're "testing" a lot of stuff at the same time, why don't you start out with the inner for loop removed (where z count from 0 to 8) and set z to a fixed value of 0. only 1/8th of your LEDs should light up, but it's enough to test the colour behaviour.

Next, are you sure you wake up from low power mode in the right time? Just for a short test replace it temporarily with a __delay_cycles(10000) to see what's happening.

Then, describe how the erratic stuff happens, is it going too fast, can you still make out the different colours (although too fast)?

Also, try to put the call to updateTCL() in the main loop instead of the timer interrupt, just after going to low power mode. SPI communication might take up quite a while of time, you preferably do not do this in your timer interrupt.

Link to post
Share on other sites
// Why is this a while loop? You have a variable, you initialize it, you test it after every iteration. This is a perfect position for a for loop.
void updateTLC()
{
	u_char ledCounter = NUMBER_OF_LEDS >> 1; //NUMBER_OF_LEDS


	while (ledCounter-- > 0)
	{
		u_char i = ledCounter << 1;
		sendMOSI(leds[i + 1]);
		sendMOSI(leds[i]);
	}
}

// Like this
void updateTLC()
{
	for(u_char ledCounter = NUMBER_OF_LEDS >> 1; ledCounter-- > 0;)
	{
		sendMOSI(leds[(ledCounter << 1) + 1]);
		sendMOSI(leds[(ledCounter << 1)]);
	}
}

It looks like you're clocking out the data for your LEDs, but the clocking behaviour is in your interrupt. Why don't you put it in here, as it is the natural place for it to happen (the reset stuff is related to the SPI stuff, not to the timer stuff).

void updateTLC()
{
    setHigh(BLANK_PIN);
    pulse(XLAT_PIN);
    setLow(BLANK_PIN);
    for(u_char ledCounter = NUMBER_OF_LEDS >> 1; ledCounter-- > 0;)
    {
        sendMOSI(leds[(ledCounter << 1) + 1]);
        sendMOSI(leds[ledCounter << 1]);
    }
}
Link to post
Share on other sites

Hey, I'm at university all day today but once I get home I'll definitely try your suggestions. With regard to the updateTLC() function, I've never had problems with it before so I'm not sure that's where the issue lies. I'll give it a go later on and let you know my results. Thanks again!

Link to post
Share on other sites

You might be experiencing some overruns there.

First, try changing timer's clock to give SPI more time

TACTL = TASSEL_2 + MC_1 + ID_1; // SMCLK, up mode, 1:2
//or
TACTL = TASSEL_2 + MC_1 + ID_2; // SMCLK, up mode, 1:4
//or
TACTL = TASSEL_2 + MC_1 + ID_3; // SMCLK, up mode, 1:8

See what works.

 

Then change the line below, you don't need do/while here

//from
pulse(SCLK_PIN);
// to
P1OUT |= SCLK_PIN; P1OUT &= ~SCLK_PIN;
// or
#define pulseTLC() P1OUT |= SCLK_PIN; P1OUT &= ~SCLK_PIN

 

 

I think you should also rewrite your SPI to use hardware.

The nice thing about 2331 is that it has USI, and USI supports 12 bit SPI.

 

BTW, this is how my code works

1. timer's ISR BLANKs and XLATs every 0xFFF. This is important because after 0xFFF GSCLKs, your LEDs go dark.

2. the little conditional inside ISR controls how often TLCs GS data is updated, it basically sets the frame rate. This gives you lots of time to update your data in main.

 

 

As for while and for, there's one more stack push/pop in the while function, but the actual loop looks pretty much the same (same number of instructions.)

updateTLCFor:  ; setup
c0ec:   120A                PUSH    R10
c0ee:   427A                MOV.B   #8,R10; for(ledCounter = NUMBER_OF_LEDS >> 1; ledCounter-- > 0;)
c0f0:   3C0E                JMP     ($C$DW$L$updateTLC2$2$E)
;actual loop
c0f2:   4A4F                MOV.B   R10,R15; sendMOSI(leds[(ledCounter << 1) + 1]);
c0f4:   5F0F                RLA.W   R15
c0f6:   5F0F                RLA.W   R15
c0f8:   4F1C 0012           MOV.W   0x0012(R15),R12
c0fc:   12B0 C178           CALL    #sendMOSI	
c100:   4A4F                MOV.B   R10,R15; sendMOSI(leds[(ledCounter << 1)]);
c102:   5F0F                RLA.W   R15
c104:   5F0F                RLA.W   R15
c106:   4F1C 0010           MOV.W   0x0010(R15),R12
c10a:   12B0 C178           CALL    #sendMOSI
c10e:   4A0F                MOV.W   R10,R15; for(ledCounter = NUMBER_OF_LEDS >> 1; ledCounter-- > 0;) ($C$DW$L$updateTLC2$2$E)
c110:   835A                DEC.B   R10
c112:   934F                TST.B   R15
c114:   23EE                JNE     ($C$L3)
;end of loop
c116:   413A                POP.W   R10
c118:   4130                RET     


updateTLCWhile: ; setup
c0bc:   120A                PUSH    R10
c0be:   1209                PUSH    R9  	
c0c0:   4279                MOV.B   #8,R9; u_char ledCounter = NUMBER_OF_LEDS >> 1; //NUMBER_OF_LEDS  	
c0c2:   3C0E                JMP     ($C$DW$L$updateTLC1$2$E); while (ledCounter-- > 0)
;actual loop
c0c4:   490A                MOV.W   R9,R10; u_char i = ledCounter << 1; ($C$L1)
c0c6:   5A4A                RLA.B   R10
c0c8:   4A4F                MOV.B   R10,R15; sendMOSI(leds[i + 1]);
c0ca:   5F0F                RLA.W   R15
c0cc:   4F1C 0012           MOV.W   0x0012(R15),R12
c0d0:   12B0 C178           CALL    #sendMOSI
c0d4:   4A4A                MOV.B   R10,R10; sendMOSI(leds[i]);
c0d6:   5A0A                RLA.W   R10
c0d8:   4A1C 0010           MOV.W   0x0010(R10),R12
c0dc:   12B0 C178           CALL    #sendMOSI
c0e0:   490F                MOV.W   R9,R15; while (ledCounter-- > 0) ($C$DW$L$updateTLC1$2$E)
c0e2:   8359                DEC.B   R9
c0e4:   934F                TST.B   R15
c0e6:   23EE                JNE     ($C$L1)
;end of loop
c172:   4139                POP.W   R9
c174:   413A                POP.W   R10
c176:   4130                RET    
Link to post
Share on other sites

Right, I've made the following changes:

TACTL = TASSEL_2 + MC_1 + ID_3; // SMCLK, up mode, 1:1
....
void main(void)
{
	init();
	updateTLC();

	P1OUT |= (XLAT_PIN);
	P1OUT &= ~(XLAT_PIN);

	short int hue = 0;
	const unsigned char val = 255;
	const unsigned char sat = 255;
	const int z = 0;

	_bis_SR_register(GIE);

	for(;
	{
		allcolsON();
		//for( z = 0 ; z < 8 ; z++)
		//{
			if (hue < 60)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,sat,val);
			}
			else if (hue < 120)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,sat,val);
			}
			else if (hue < 180)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,sat,val);
			}
			else if (hue < 240)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,sat,val);
			}
			else if (hue < 300)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,sat,val);
			}
			else if (hue < 360)
			{
				HSV2RGB(&leds[z],&leds[z+8],&leds[z+16],hue,sat,val);
			}
			else
			{
				hue = 0;
			}
		//}
		hue++;
		//_bis_SR_register(LPM0_bits);
		 __delay_cycles(18000);
	}
}
#pragma vector = TIMER0_A0_VECTOR
		__interrupt void Timer_A0(void) 
{
	static const int Cnt = 0x08; // 0x08 when sat is 255

	P1OUT |= (BLANK_PIN);
	P1OUT |= (XLAT_PIN);
	P1OUT &= ~(XLAT_PIN);
	P1OUT &= ~(BLANK_PIN);
	timerCounter++;
	if (timerCounter == Cnt) { // 0x08 - 2ms * 8 = 16.384ms, ~61Hz
		updateTLC();
		timerCounter = 0;
		_bic_SR_register_on_exit(LPM0_bits);
	}
}

void sendMOSI(u_int mosi) {
	u_char c = 0;
	while (c < 12)
	{
		(mosi & 0x0800) ? (P1OUT |= MOSI_PIN) : (P1OUT &= ~MOSI_PIN);
		P1OUT |= SCLK_PIN;
		P1OUT &= ~SCLK_PIN;
		mosi <<= 1;
		c++;
	}
}

Here's a link to the video showing exactly what is appearing when this code is run:

 

All the colours are being shown, but it's such a strange order - when it should cycle through hues 0 - 360 degrees. Moving updateTLC() from the interrupt to the main loop makes the LEDs cycle through the colours in a better sequence, but it looks as though the hue is moving back and forwards before progressing onto the next colour. Here's another video - hopefully you'll know what I mean. 

// end of main()
		hue++;
		_bis_SR_register(LPM0_bits);
		 updateTLC();
}
Link to post
Share on other sites

Again, you are trying to control your timing in the main loop.

Do not use _delay_cycles(), it's evil (and I know something about evil, I am Dr. Doofenshmirtz after all.)

HSV2RGB takes about 450 clock cycles, with other conditionals probably somewhere about 500, so this function is not a problem.

 

main and ISR should run independently.

 

ISR restarts PWM to make sure we don't have dark LEDs and flickering. It is also used to time animation and push updated data to TLC.

Once it's time for next animation frame, it wakes MCU and allows main loop to run (once.)

 

main loop's job is to update data for the next frame and then go back to sleep. That update should happen faster than frame rate, which I see is not a problem here.

 

 

BTW, short in MSP430 C is the same thing as int so short int is redundant

 

 

main {
	...
	setup
	...
	
	for(;
	{
		//OK, it's time to calculate new data
		hue = something * someParam;
		// now update LED array using my HUE function
		for each LED {
			HUE(...)
		}
		// OK, done updating LED array with new values
		// let's go back to sleep, ISR will update TLC when the time is right
		_bis_SR_register(LPM0_bits);
	}
}

ISR {
	// 4096 GS clock cycles have been generated, time to restart PWM
	clockXLATandBLANK
	// increase timer counter
	timerCounter++;
	if (timerCounter == 0x08) // is it time to for next frame?
		{
		    updateTLC(); // data was already prepared by main loop when it was awake last time
			timerCounter = 0;
			_bic_SR_register_on_exit(LPM0_bits); // wake up main loop so that it can prepare data for the next frame
		}
}
Link to post
Share on other sites

Each time the interrupt occurs you do
P1OUT |= (BLANK_PIN);
    P1OUT |= (XLAT_PIN);
    P1OUT &= ~(XLAT_PIN);
    P1OUT &= ~(BLANK_PIN);

but only every 8 times you do updateTLC().

Either use the timer or delay_cycles, not both. I suppose your two pieces of code are gravely interfering with eachother. You do updateTLC in both main and interrupt, but why? I mean really, why? I doubt you can explain yourself why you're doing it this way.

You'd best go with RobG's approach and only update the LEDs in the main loop, then go to LPM and let the timer wake you from it. Poersonally I'd move the blank/xlat/updatetlc stuff to the main too, and do only wakeup from the interrupt (plus some timekeeping).

Link to post
Share on other sites

BLANK and XLAT latches data that is already in TLC's buffer and restarts PWM, this part must be perfectly timed.

updateTLC sends data to TLC only when it is necessary, otherwise TLC will use whatever it already has in it's buffer.

You don't want to update TLC too often.

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.

Guest
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...