Jump to content

Search the Community

Showing results for tags 'shift register'.

More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


  • News
    • Announcements
    • Suggestions
    • New users say Hi!
  • Spotlight!
    • Sponsor Spotlight
    • Sponsor Giveaways
  • Energia
    • Energia - MSP
    • Energia - TivaC/CC3XXX
    • Energia - C2000
    • Energia Libraries
  • MSP Technical Forums
    • General
    • Compilers and IDEs
    • Development Kits
    • Programmers and Debuggers
    • Code vault
    • Projects
    • Booster Packs
    • Energia
  • Tiva-C, Hercules, CCXXXX ARM Technical Forums
    • General
    • SensorTag
    • Tiva-C, Hercules, CC3XXX Launchpad Booster Packs
    • Code Vault
    • Projects
    • Compilers and IDEs
    • Development Kits and Custom Boards
  • Beagle ARM Cortex A8 Technical Forums
    • General
    • Code Snippets and Scripts
    • Cases, Capes and Plugin Boards
    • Projects
  • General Electronics Forum
    • General Electronics
    • Other Microcontrollers
  • Connect
    • Embedded Systems/Test Equipment Deals
    • Buy, Trade and Sell
    • The 43oh Store
    • Community Projects
    • Fireside Chat
  • C2000 Technical Forums
    • General
    • Development Kits
    • Code Vault
    • Projects
    • BoosterPacks


There are no results to display.

Find results in...

Find results that contain...

Date Created

  • Start


Last Updated

  • Start


Filter by number of...


  • Start



Website URL





Found 3 results

  1. Hi, I've just started playing with the MSP430 (MSP430G2252) and i'm having lots of problems with getting myself up to speed. If anyone could help me out on the basic, it would be greatly appreciated... my background is in the hardware and i am no expert at programming For the beginning of my project (just to get me working on the right track), i'm trying to make a countdown with 2x 7segment displays while using a 16bit shift register. At startup, i need to read the value of Port1 (to find out the value to start the count from), calculate the 2x8bit value to be sent to the shift register .. then send them (in the correct order) and keep the value displayed for 1sec, then using the same process, decrease the value by one till it counts down to 0sec and then would go blank until next reboot or if the reset button is pressed. I've looked for sample codes to get started, but it's only confusing me more. http://e2e.ti.com/blogs_/b/designproject/archive/2013/02/04/mikro-elektronika-39-s-7-segment-quot-click-board-quot-with-msp430-launchpad-and-energia.aspx http://www.geeetech.com/wiki/index.php/Arduino_7_segment_LED_timer_with_74HC595_module http://kimansfield.com/MSP430.html https://github.com/powercat/msp430-7seg/blob/master/7segment_counter_4094.c www.mikroe.com/downloads/get/1884/7seg_click_manual.pdf Port 1, pin 0 to 5 is for used to get the value for the start of the countdown and are pulled-up by default using external resistor (pulled down using the dip switch to enabled them) .. example: if pin 0 and pin 1 are enabled (pulled down) the countdown will count from 3 (1+2) example: if pin 1, pin 3 and pin 4 are enabled (pulled down) the countdown will count from 26 (2+8+16) example: if pin 0, pin 1, pin 2, pin 3 and pin 5 are enabled (pulled down) the countdown will count from 39 (1+2+4+32) p1.0 = 1 p1.1 = 2 p1.2 = 4 p1.3 = 8 p1.4 = 16 p1.5 = 32 p1.6 = Not used p1.7 = Not used the Data pin is p4.3 the Latch pin is p4.0 the Clock pin is p3.3 the Reset pin is p4.2 //reset button (pulled high with external resistor, and activated when low) the Countdown value is Port 1 .. pin 0 to 5 (6 & 7 are not used) and all pins are pulled high with external resistor, activated when low my connections are very similar to the 2x seven segment displays and 2x 74HC595 found here: www.mikroe.com/downloads/get/1884/7seg_click_manual.pdf The only differences are that i'm using a different shift register that has 16 outputs (16bit shift register instead of 2x8). The outputs are connected in alphabetical order to the 2x 7 segments of the display... Display on the Right side (lower digits) Out0 = Segment A Out1 = Segment B Out2 = Segment C Out3 = Segment D Out4 = Segment E Out5 = Segment F Out6 = Segment G Out7 = Not Connected Display on the Left side (higher digits) Out8 = Segment A Out9 = Segment B Out10 = Segment C Out11 = Segment D Out12 = Segment E Out13 = Segment F Out14 = Segment G Out15 = Not Connected If the reset button is pressed, the program should restart and get the Port1 value and countdown.. else, it would not do anything. I already have a hardware debounce on the pin (resistor/capacitor).. I don't know if i should still need it in my program I have an external crystal of 4.194khz connect to it, but I can remove it if not required An example would look like this, at startup, assuming Port1 is set to 12, you would see 12 (for 1sec), then 11 (for 1sec), 10 (for 1sec), 9 (for 1sec), 8 (for 1sec), 7 (for 1sec), 6 (for 1sec), 5 (for 1sec), 4 (for 1sec), 3 (for 1sec), 2 (for 1sec), 1 (for 1sec), 0 (for 1sec), then "Blank" it would stay blank until the reset button is pressed I've tried to get started with the code but I am getting confused on how I can read the whole port1 and make it countdown from that value Here's my start of the code for the Code Composer Studio but can't figure out the rest.. should i use "Do".. or "While" .. or "For" to calculate the value of the count from Port1 input (countdown value) and make it count from that value down to zero and then stay blank ======== int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer P1DIR &= ~0x63; // Set P1 0-5 to input direction P1SEL &= ~0x63; // initialize Port 1 (pin 0-5) to 0, selecting coundown value P3DIR |= 0x08; // Set P3.3 to output direction P4DIR |= 0x09; // Set P4.0 & P4.3 to output direction P4DIR &= ~0x04; // Set P4.2 to input direction ========== I've also been trying to modify the code below for Energia to fit my needs, but I don't know how to add the Port1 input (countdown value) to it as well and make it count from that value... personnaly, i would prefer the code to be written for the Code Composer Studio since i don't know if Energia can compile for the MSP430G2252 http://e2e.ti.com/blogs_/b/designproject/archive/2013/02/04/mikro-elektronika-39-s-7-segment-quot-click-board-quot-with-msp430-launchpad-and-energia.aspx //Define which pins will be used for controlling the Shift Register int dataPin = P4_3; //shift register data pin ("SDI") set to MSP430 pin 4.3 int latchPin = P4_0; //shift register latch pin ("LATCH") set to MSP430 pin 4.0 int clockPin = P3_3; //shift register clock pin ("SCK") set to MSP430 pin 3.3 int resetPin = P4_2; //Reset pin set to MSP430 pin 4.2 int countPin = P1; //Countdown value pin set to MSP430 port 1 //corresponding digit displayed on LED: // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 byte counter[10] = {B01111110, B00001010, B10110110, B10011110, B11001010, B11011100, B11111100, B00001110, B11111110, B11011110}; byte blank = 0; //used as a blank to push digit to right LED void setup() { pinMode(dataPin, OUTPUT); //Configure pin as output pinMode(latchPin, OUTPUT); //Configure pin as output pinMode(clockPin, OUTPUT); //Configure pin as output pinMode(resetPin, INPUT); //Configure pin as input pinMode(countPin, INPUT);} //Configure port as input void loop() { for (int i = 0; i < 10; i++) { digitalWrite(latchPin, LOW); //Pull latch LOW to start sending data shiftOut(dataPin, clockPin, MSBFIRST, counter); //Send the data shiftOut(dataPin, clockPin, MSBFIRST, blank); //Send blank to push digit to the right 7 Seg LED digitalWrite(latchPin, HIGH); //Pull latch HIGH to stop sending data delay(1000); } } ============
  2. Earlier this year I happened to be in Singapore in transit, and took the opportunity to visit Sim Lim Tower - a high-rise mall full of electronic components shops! Amazing place, and amongst other things (including super-cheap kits for the kids to build!) I picked up three 5x7 LED matrix panels for a dollar each (!!). They didn't have any part numbers that I could see, but after experimentation they turned out to be row-anode devices and once I figured out the pinout I decided to build a project out of them. As any of us who have children know, it's a daily battle to get kids to brush their teeth for long enough, and as any of us who have children also know, time spent on projects goes down better if there's a kid angle to it. So I decided to make a tooth brush timer, that will display a countdown from two minutes - interspersed with inspirational text and probably amusing patterns and other things to keep the kids entertained during their twice-daily two-minute ordeal. Poor things. Being given to doing things the hard way, I decided to design two boards - one for the LED panels, and one for the controller. I'll get to the controller board in a later post because it's quite complicated (since the board fab place makes 10 identical boards I decided to try to make it as multi-purpose as possible). The LED boards though are simpler, they just use a 4094 shift register to handle the columns (or rows, I decided to use my three matrices abutted end to end rather than side to side, giving me a display that's five LEDs high and twenty-one across. I found a nice 5x5 bitmap font on dafont.com, and decided that I had enough space for what I needed to display. Because if all the LEDs are on the 4094 will be over it's specified current limit, it drives the columns through seven PNP transistors. This meant quite a bit of routing, which is what led me to use a board fab house rather than attempt it all on veroboard. So, onto the code (I have attached the eagle files if anyone is interested). I wanted to use the USI module to drive the 4094's. Looking at the datasheet for a 4094, it clocks in it's data on a rising edge of the clock. So the USI module will need to be configured thusly (I'm running the CPU at 12Mhz). // Reset USI logic to allow configuration USICTL0 |= USISWRST; // Setup serial output for a 4094 shift register USICTL0 = USIPE6 // SDO enabled + USIPE5 // CLK enabled + USIMST // master mode + USIOE // output enable + USISWRST // leave in reset ; // clock phase = 1, interrupts enabled SICTL1 = USICKPH // phase = 1 + USIIE // interrupt enabled ; USICKCTL = USIDIV_4 // divide by 16, giving 500khz clock + USISSEL_2 // SMCLCK as clock source ; // release SPI for operation USICTL0 &= ~USISWRST; Now, the tricky part of this project is that I want to have greyscale (redscale!) on my LEDs. To do this I will have to not only row-scan the matrix, but also PWM each LED individually. And I want to do all this in the USI interrupt handler, and have a framebuffer in RAM that I can just write to at any time without having to worry about getting the LEDs to update. So first thing is the framebuffer, I'm just using one LED matrix at the moment so it's only a 5x7 array: unsigned char framebuffer[5][8]; // greyscale framebuffer So, for those unfamiliar with how to drive these types of LED matrices, here's a bullet-pointed flow-chart. Start at the first row. Clock bits into the 4094 shift register, corresponding to which LEDs in the current row are on. Because I'm using PNP transistors as high-side switches, a zero in the 4094 outputs will correspond to an LED being on. Once the bits are clocked in, set the 'strobe' input into the 4094 to high. This will latch the outputs of the 4094, causing them all to change at once to whatever you just clocked in. Now that the high-side transistors are all either on or off, according to which LED in the current row you want to be on, it's time to turn that row on using the low-side switch for that row. Of course there could be quite a bit of current flowing out through the row pin if all the LEDs in that row are on, so it's not safe to just hook it up to a GPIO pin. A FET is instead used as a low-side switch. Now the row is lit up. Move to the next row and goto 2. If we're at the last row, then instead goto 1 (which means start over). The above method, if run fast enough, will cause all the LEDs to appear illuminated in whatever pattern you desire. But it won't allow brightness control of individual LEDs. To get that we need another variable, that I'll call PWM. PWM will start at zero, and will be incremented at step 1 of the above bullet-pointed flowchart. When it reaches 16, it will be reset back to zero. So it's a rolling counter that will count up each time a frame is output to the matrix, and will roll over at 16. Using this, and the greyscale framebuffer above, we can modify the flowchart so that instead of just clocking in whichever LEDs are on into the 4094, we clock in whichever LEDs have a brightness value that is greater than the current PWM counter. Thus, when the framebuffer entry is zero for a particular LED, that LED is never illuminated because it's brightness value (zero) is never greater than the PWM value (zero to fifteen). And when the framebuffer entry is sixteen, it's always greater than the PWM counter, and thus that LED is illuminated every frame. In between values illumiate the LED for varying numbers of frames, which - if you run the whole process fast enough - will cause them to appear dimmer. The heart of this code is the following loop, which I would love some advice on how to optimise: output = 0; for(bit = 8; bit ; bit--) { output <<= 1; output |= (framebuffer[row][bit] > pwm) ? 0 : 1; // on if over pwm } This loop calculates what to output to the 4094 shift register for each row. It's quite alot of work for an interrupt handler, and it needs to be three times more work once I add the additional two LED panels. I'm sure the compiler in CCS does a good job of figuring out the loop and optimising it for me, but I should take a look at the assembly output and determine if I can do any better. Anyway, to kickstart the process, the main program calls NextRow(), and then sets up a timer and fiddles with the framebuffer at intervals. So, here's NextRow and the USI interrupt handler: unsigned char pwm = 0; unsigned char row = 0; void NextRow() { unsigned char bit; unsigned char output; // strobe low ready for next thingy P1OUT &= ~BIT3; // next row's data - work out if each pixel should be on output = 0; for(bit = 8; bit ; bit--) { output <<= 1; output |= (framebuffer[row][bit] > pwm) ? 0 : 1; // on if over pwm } USISRL = output; // 8 bits out, we'll come back to _usi once these bits have been clocked out. USICNT = 8; } #pragma vector = USI_VECTOR interrupt void _usi() { USICTL1 &= ~USIIFG; // reset interrupt flag // turn off rows P2OUT = 0; // latch data P1OUT |= BIT3; // Strobe high // turn on rows P2OUT = (1 << row); // next row row++; if (row == 5) { pwm++; pwm &= 0x0F; // loop pwm back to zero when it hits sixteen row= 0; // start at row zero again. } NextRow(); } I've left alot of stuff out here, setting up the clock module and the GPIO pins etc etc. Also there's code in the project that makes a pretty (ish) pattern, and the displays some numbers. The code and eagles files are attached, and assuming I can use the video feature of BBcode correctly, here's a video! http://www.youtube.com/watch?v=gvPZ8LyGYGY --Edit--- Well that youtube embed didn't work. Here's a link. How do you embed videos anyway? LED control.zip
  3. Hello everyone! I'm continuing my project of creating an RGB LED matrix capable of displaying live images being transmitted from a laptop via a serial cable to the MSP430G2553. At the moment, I'm coding four 8x8 Common Anode RGB LED matrices joined together to create a 16x16 display. Hardware I'm using: - 3 * TLC5940s (one for each colour) - 2 * 74HC595 shift registers (drives the columns/anodes) I'm using code provided by RobG from this link <http://forum.43oh.com/topic/2315-tlc5940-examples/> and this one <http://forum.43oh.com/topic/3328-rgb-to-hsv-conversion-with-msp430g2231-help/#entry29106> in order to drive the LEDs with PWM enabled. BUT, the problem I'm having is that I'm trying to allow every pixel to have different colours, but when running, the microcontroller isn't refreshing the pixels fast enough so there is MASSIVE flickering - which isn't ideal.... Here is the code from which I am working : feel free to insult :-P #include <msp430g2553.h> #include <msp430.h> // Need to sort hsv2rgb because yellow is pish... // u_long is 32 bits so 2^32 - 1 is max value. Need more for 32x32 matrix // TLC inputs #define VPRG_PIN BIT0 // TIE TO GND? #define GSCLK_PIN BIT4 #define SCLK_PIN BIT5 #define DATA BIT6 // DS -> 1.6 | 595 DATA PIN #define MOSI_PIN BIT7 #define MOSI595 BIT2 // 595 data pin ? THIS ISNT DOING ANYTHING #define DCPRG_PIN BIT0 // TIE IT TO GND? #define XLAT_PIN BIT1 #define BLANK_PIN BIT2 #define CLOCK BIT3 // SH 11 -> 2.3 // 595 OUTPUTS #define LATCH BIT4 // ST 12 -> 2.4t typedef unsigned char u_char; typedef unsigned int u_int; typedef unsigned short u_short; typedef unsigned long u_long; // ================================// // Prototypes // // ================================// void init( void ); void SPI_setup( void ); void updateTLC( void ); void shiftOut( u_long ); void HSV2RGB( u_short*, u_short*, u_short*, short, u_char); void set_row_char_hue (u_char, u_long, short, u_char); void row_refresh(u_char,short,short,short,short,short,short,short,short,short,short,short,short,short,short,short,short); #define NUMBER_OF_OUTS 48 // TLC OUTPUTS #define NUMBER_OF_ROWS 8 #define NUMBER_OF_COLUMNS 16 #define max_COLUMN NUMBER_OF_COLUMNS-1 #define max_ROW NUMBER_OF_ROWS-1 #define OFF 0 u_short leds[NUMBER_OF_OUTS]; // 0 - 15 Red Rows, 16 - 31 Blue Rows, 32 - 47 Green Rows {0, } u_char timerCounter = 0; void init(void) { WDTCTL = WDTPW + WDTHOLD; // disable WDT BCSCTL1 = CALBC1_16MHZ; // 16MHz clock DCOCTL = CALDCO_16MHZ; BCSCTL2 |= DIVS_0; // divide clock by 1 P1OUT &= ~(VPRG_PIN); P1DIR |= (VPRG_PIN + GSCLK_PIN + DATA); // port 1.4 configured as SMCLK out P1SEL |= GSCLK_PIN; P2DIR |= (BLANK_PIN + XLAT_PIN + CLOCK + LATCH + DCPRG_PIN); P2OUT &= ~(BLANK_PIN + XLAT_PIN); P2OUT &= ~DCPRG_PIN; // setup timer CCR0 = 0xFFF; TACTL = TASSEL_2 + MC_1 + ID_0; // SMCLK, up mode, 1:1 CCTL0 = CCIE; // CCR0 interrupt enabled } void SPI_setup(void) { // setup UCA0 ----UCA0 ISNT DOING ANYTHING YET! SHOULD I CONFIGURE THE 595's TO BE CONTROLLED BY SPI? P1SEL |= MOSI595; // p1.2 P1SEL2 |= MOSI595; // UCA0SIMO UCA0CTL0 = UCCKPH + UCMSB + UCMST + UCSYNC; // data captured on 1st UCLK edge/changed on follwing edge, MSB first, master, 3-pin SPI,synchronous UCA0CTL1 |= UCSSEL_2; // SMCLK UCA0BR0 |= 0x01; // 1:1 UCA0BR1 = 0; UCA0CTL1 &= ~UCSWRST; // clear SW // setup UCB0 P1SEL |= SCLK_PIN + MOSI_PIN; // pins 5 + 7 P1SEL2 |= SCLK_PIN + MOSI_PIN; // UCB0CLK + UCB0SIMO UCB0CTL0 = UCCKPH + UCMSB + UCMST + UCSYNC; // data captured on 1st UCLK edge/changed on follwing edge, MSB first, master, 3-pin SPI,synchronous UCB0CTL1 |= UCSSEL_2; // SMCLK UCB0BR0 |= 0x01; // 1:1 UCB0BR1 = 0; UCB0CTL1 &= ~UCSWRST; // clear SW } void main(void) { init(); SPI_setup(); updateTLC(); P2OUT |= (XLAT_PIN); P2OUT &= ~(XLAT_PIN); short o = 240; short y = 60; // yellow short b = 240; // blue short hue = 0; _bis_SR_register(GIE); for(; { // creates box image row_refresh(0, b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,; row_refresh(1, b,y,y,y,y,y,y,y,y,y,y,y,y,y,y,; row_refresh(2, b,y,b,b,b,b,b,b,b,b,b,b,b,b,y,; row_refresh(3, b,y,b,y,y,y,y,y,y,y,y,y,y,b,y,; row_refresh(4, b,y,b,y,b,b,b,b,b,b,b,b,y,b,y,; row_refresh(5, b,y,b,y,b,y,y,y,y,y,y,b,y,b,y,; row_refresh(6, b,y,b,y,b,y,b,b,b,b,y,b,y,b,y,; row_refresh(7, b,y,b,y,b,y,b,y,y,b,y,b,y,b,y,; row_refresh(8, b,y,b,y,b,y,b,y,y,b,y,b,y,b,y,; row_refresh(9, b,y,b,y,b,y,b,b,b,b,y,b,y,b,y,; row_refresh(10, b,y,b,y,b,y,y,y,y,y,y,b,y,b,y,; row_refresh(11, b,y,b,y,b,b,b,b,b,b,b,b,y,b,y,; row_refresh(12, b,y,b,y,y,y,y,y,y,y,y,y,y,b,y,; row_refresh(13, b,y,b,b,b,b,b,b,b,b,b,b,b,b,y,; row_refresh(14, b,y,y,y,y,y,y,y,y,y,y,y,y,y,y,; row_refresh(15, b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,; _bis_SR_register(LPM0_bits); // go to sleep } // end of for(; loop } void updateTLC(void) // RobG's code { u_char ledCounter = NUMBER_OF_OUTS >> 1; while (ledCounter-- > 0) { u_char i = ledCounter << 1; UCB0TXBUF = leds[i + 1] >> 4; while (!(IFG2 & UCB0TXIFG)); // TX buffer ready? u_char unib = leds[i + 1] << 4; u_char lnib = (leds[i] >> 8) & 0x0F; UCB0TXBUF = unib | lnib; while (!(IFG2 & UCB0TXIFG)) ; // TX buffer ready? UCB0TXBUF = leds[i]; while (!(IFG2 & UCB0TXIFG)); // TX buffer ready? } } void row_refresh(u_char row,short a,short b,short c,short d,short e,short f,short g,short h,short i,short j,short k,short l,short m,short n,short o,short p) { // this function checks if led is supposed to be ON // for example, if row = 0, and a = 360 then the top left led is OFF // if a = 120, then the led will be ON, and will be assigned the appropriate hue (green) u_long col_data = 0x0000; if(a < 360){col_data = 0x8000; set_row_char_hue(row,col_data,a,1);} // 0 if(b < 360){col_data = 0x4000; set_row_char_hue(row,col_data,b,1);} // 1 if(c < 360){col_data = 0x2000; set_row_char_hue(row,col_data,c,1);} // 2 if(d < 360){col_data = 0x1000; set_row_char_hue(row,col_data,d,1);} // 3 if(e < 360){col_data = 0x0800; set_row_char_hue(row,col_data,e,1);} // 4 if(f < 360){col_data = 0x0400; set_row_char_hue(row,col_data,f,1);} // 5 if(g < 360){col_data = 0x0200; set_row_char_hue(row,col_data,g,1);} // 6 if(h < 360){col_data = 0x0100; set_row_char_hue(row,col_data,h,1);} // 7 if(i < 360){col_data = 0x0080; set_row_char_hue(row,col_data,i,1);} // 8 if(j < 360){col_data = 0x0040; set_row_char_hue(row,col_data,j,1);} // 9 if(k < 360){col_data = 0x0020; set_row_char_hue(row,col_data,k,1);} // 10 if(l < 360){col_data = 0x0010; set_row_char_hue(row,col_data,l,1);} // 11 if(m < 360){col_data = 0x0008; set_row_char_hue(row,col_data,m,1);} // 12 if(n < 360){col_data = 0x0004; set_row_char_hue(row,col_data,n,1);} // 13 if(o < 360){col_data = 0x0002; set_row_char_hue(row,col_data,o,1);} // 14 if(p < 360){col_data = 0x0001; set_row_char_hue(row,col_data,p,1);} // 15 } void set_row_char_hue (u_char row, u_long col_data, short hue, u_char bool) { u_char led = 0; u_long byte; for(led = 0 ; led < 16 ; led++ ) { byte = (col_data>>led)&(0x01); if( byte ) { HSV2RGB( &leds[row], &leds[row + 32], &leds[row + 16], hue, bool); //on; shiftOut( col_data ); } } // turn off leds leds[row] = OFF; leds[row+32] = OFF; leds[row+16] = OFF; } void HSV2RGB(u_short* r, u_short* g, u_short* b, short h, u_char bool) { const u_char s = 255; u_char v = 255; u_char i, p, q, t; u_short 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; } if ( bool == 1 ) { *r *= v/16; *g *= v/16; *b *= v/16; } else { *r *= 0; *g *= 0; *b *= 0; } } #pragma vector = TIMER0_A0_VECTOR __interrupt void Timer_A0(void) { // 4096 GS clock cycles have been generated, time to restart PWM P2OUT |= (BLANK_PIN); P2OUT |= (XLAT_PIN); P2OUT &= ~(XLAT_PIN); P2OUT &= ~(BLANK_PIN); // increase timer counter timerCounter++; if (timerCounter == 1) // this is also from RobG, except updateTLC is every interrupt because otherwise it is far too slow { // 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 } } void shiftOut(u_long val) { P2OUT &= ~LATCH; int i; for (i = 0; i < 16; i++) // iterate over each bit 16 { if(val & (1 << i)) { P1OUT |= DATA; } else { P1OUT &= ~DATA; } P2OUT |= CLOCK; // PULSE CLOCK P2OUT ^= CLOCK; } // } P2OUT |= LATCH; // PULSE LATCH P2OUT &= ~LATCH; } If anyone has any suggestions on how to improve this code, it will be greatly appreciated, because I've really hit a wall with it. I did think that using SPI P1.2 for UCA0SIMO instead of the shiftOut() function might be a solution but I don't know how to go about doing that. Keep in mind that soon I'll be using P1.1 for RXD. Cheers!