Radio Shack Tri Color Led Question - how to change output pin (solved)

I got this from a friend the other day and I can get it up and working with the code they provided no problem (the link below and full code attached). I wanted to add it too a pre-existing project that is already using the A0 pin on my arduino uno. this block at the top appears to be where it sets the pin but I can't figure out how to change it.

#define DATA_1 (PORTC |=  0X01)    // DATA 1    // for UNO
#define DATA_0 (PORTC &=  0XFE)    // DATA 0    // for UNO
#define STRIP_PINOUT (DDRC=0xFF)    // for UNO

if anyone can explain how this port stuff works and (if I am completely off on how to change the pin) how to change the output pin to the led strip you would save my project from being boring.

Thanks plenty!

Link:

full code:

#include <avr/pgmspace.h>

#define DATA_1 (PORTC |=  0X01)    // DATA 1    // for UNO
#define DATA_0 (PORTC &=  0XFE)    // DATA 0    // for UNO
#define STRIP_PINOUT (DDRC=0xFF)    // for UNO

PROGMEM const unsigned long pattern_test_red[10][10]={
  {0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000},
  {0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000},
  {0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000},
  {0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000},
  {0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000,0x000000},
  {0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000,0x000000},
  {0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000,0x000000},
  {0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000,0x000000},
  {0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000,0x000000},
  {0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0x000000,0xff0000},
};
//there are more patterns but i deleted them to save space
};
void setup() {                
  STRIP_PINOUT;        // set output pin - DEBUG: should auto detect which mother board for use
  reset_strip();
}
void loop() 
{
  send_1M_pattern(pattern_test_red, 10, 500);
  delay(500);
  send_1M_pattern(pattern_test_blue, 10, 500);
  delay(500);
  send_1M_pattern(pattern_test_green, 10, 500);
  delay(500);
  send_1M_pattern(pattern_test_white, 10, 500);
  delay(500);
  send_1M_pattern(pattern_test_comet1, 10, 70);
  delay(500);
  send_1M_pattern(pattern_test_comet2, 10, 70);
  delay(500);
  send_1M_pattern(pattern_test_comet3, 10, 70);
  delay(500);
  while (1)
  {
    send_1M_pattern(pattern_test_rainbow, 10, 70);
  }
}
void send_1M_pattern(const unsigned long data[][10], int pattern_no, int frame_rate)
{
  int i=0;
  int j=0;
  uint32_t temp_data;
  for (i=0;i<pattern_no;i++)
  {
    noInterrupts();
    for (j=0;j<10;j++)
    {
      temp_data=pgm_read_dword_near(&data[i][j]);
      send_strip(temp_data);
    }
    interrupts();
    delay(frame_rate);
  }
}
void send_strip(uint32_t data)
{
  int i;
  unsigned long j=0x800000;
  for (i=0;i<24;i++)
  {
    if (data & j)
    {
      DATA_1;
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");    
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      DATA_0;
    }
    else
    {
      DATA_1;
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");
      __asm__("nop\n\t");    
      DATA_0;
    }
    j>>=1;
  } 
}
void	reset_strip()
{
  DATA_0;
  delayMicroseconds(20);
}

RadioShack-Tricolor-LED-Strip-Support-Files1.zip (1.88 MB)

Hi Gamgem,

I had the same problem too, here's why: the line
#define STRIP_PINOUT (DDRC=0xFF) // for UNO
turns all of the analog pins into outputs so you can plug the control pin for the LED in wherever you want.

It also kills off anything else you want to do with an analog pin.

I'm using this line instead of the one above to set only pin 0 to output.
#define STRIP_PINOUT (DDRC |= _BV(PORTC0)) // for UNO

And I've left my LED in analog 0 and simply moved my other pins to suit.

I've got light and temperature sensors in my other analog pins so and I now have temperature based colourful lighting that turns on and gets brighter as it gets dark.

Hope this helps you.

Going into this problem I was dead set on getting the output pin to be A5 (on an uno) to fit with a project I was working on. I knew a little about

#define STRIP_PINOUT (DDRC=0xFF)

with some help from the internet I learned it was setting all analog pins to output a pretty inconvenient line as orestal pointed out.

However looking at the lines above that actually control the output pin for the data is not as easy to figure out nor is it intuitive.
#define DATA_1 (PORTC |= 0X01) // DATA 1 // for UNO
#define DATA_0 (PORTC &= 0XFE) // DATA 0 // for UNO

If you add one to the hex for data 1 and subtract for data 0 the output is now on pin A1.
#define DATA_1 (PORTC |= 0X02) // DATA 1 // for UNO
#define DATA_0 (PORTC &= 0XFD) // DATA 0 // for UNO

But when you repeat this step making it...
#define DATA_1 (PORTC |= 0X03) // DATA 1 // for UNO
#define DATA_0 (PORTC &= 0XFC) // DATA 0 // for UNO
The pin is still A1

One more time and you get this and voila! you get pin A2
#define DATA_1 (PORTC |= 0X04) // DATA 1 // for UNO
#define DATA_0 (PORTC &= 0XFB) // DATA 0 // for UNO
A2 then has three more (for a total of four) occurrences to set A2 as output pin. As you can see a pattern is forming. every proceeding pin has double the combinations for setting it to output for the strip. I don't know why this is at all so if anyone can help please chime in. but here is a table for all the values and the pin the data will leave.
The first value is data_1 and second is data_0
(between each set the first value gets adds by one and second subtracts (i.e. from 01,FE - 03,FC the middle value is 02,FD))
A0 -- 01,FE
A1 -- 02,FD and 03,FC
A2 -- 04,FB - 07,F8
A3 -- 08,F7 - 0F,F0
A4 -- 10,EF - 1F,E0
A5 -- 20,DF - I havent tested end but it probably ends at 3F,B0
Keep in mind this is all hex (i.e. 10 doesnt equal 10 decimal it equals 16 decimal)

I'm going to necro this thread for one reason: gamgem asked an unanswered question that is very important for those new to software development to understand.

To do so, I'm going to borrow from Jon Skeet's excellent explanation on Stack Overflow.

[b]|=[/b] and [b]&=[/b] are what's known as bitwise compound assignment operators.

[b]x |= y[/b] is the same as saying [b]x = x | y[/b]

  • [b]|=[/b] will only ever add bits to the target
  • [b]&=[/b] will only ever remove bits from the target

But why the doubling of values? Understanding that is the key to knowing why the PORTC modifications actually work. Let's look at those values as decimal, hex, binary and base 2 exponents:

dec  |  base 2 exp  |  hex  |  binary
------------------------------------------
1    |     2^0      |  0x1  |  00000001
2    |     2^1      |  0x2  |  00000010
4    |     2^2      |  0x4  |  00000100
8    |     2^3      |  0x8  |  00001000
16   |     2^4      |  0x10 |  00010000
32   |     2^5      |  0x20 |  00100000

So if [b]x = 1[/b] and [b]y = 2[/b], [b]x |= y[/b] gives us a binary value of
** **00000011** **
. By assigning unique power of 2 values to each Arduino pin, we are guaranteed unique combinations when performing those bitwise compound assignments.

I hope this clears things up for some and was worth the resurrection! :wink:

Cheers ~ Jason

ps. If this low-level bit fiddling interests you and you'd like to explore further (and I mean really far!), I can't recommend the book Hacker's Delight (2ed) enough. It's simply one of a kind.