Pages: [1]   Go Down
Author Topic: Port manipulation  (Read 919 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey everyone, I'm new to this - done a few sketches of my own but I just bought an LED strip and when looking at the example sketch for it, and it works, but I can't for the life of me figure out where in this sketch it's sending data to the pins. I'm sure it's in the SendStrip() function but can't figure out exactly what line is sending data. I'm attempting to have it pulse to music and the project has been quite the challenge so far. I've spent a couple days looking at this so if anyone can offer some help I'd be immensely grateful. Thank you!

Code:

#include <avr/pgmspace.h>

// ******** DEBUG ==== should auto config to adapt different mother board *********
//#define DATA_1 (PORTF |=  0X01)    // DATA 1    // for ATMEGA
//#define DATA_0 (PORTF &=  0XFE)    // DATA 0    // for ATMEGA
//#define STRIP_PINOUT DDRF=0xFF  // for ATMEGA
#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_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},
};




// ***********************************************************************************************************
// *
// *                            Power Up Init.
// *
// *
// ***********************************************************************************************************
void setup() {                

  STRIP_PINOUT;        // set output pin - DEBUG: should auto detect which mother board for use

  reset_strip();
  //noInterrupts();

}



// ***********************************************************************************************************
// *
// *                            Main Loop
// *
// *
// ***********************************************************************************************************
void loop()
{

  
    send_1M_pattern(pattern_test_rainbow, 10, 70);


  /*
frame++;
   if(frame<=10) LEDSTRIP_PATTERN_0();
   if(10<frame<=20) LEDSTRIP_PATTERN_0();
   if(20<frame<=30) LEDSTRIP_PATTERN_0();
   if(frame>30) frame=1;
   */
  //delay(1);
}


/*******************************************************************************
 * Function Name  : send_1M_pattern
 * Description    : Transmit pattern to whole 1 meter strip
 *                  
 * Input          : pointer to ROM pattern; pattern length; frame rate
 *                  
 * Output         : None
 * Return         : None
 *******************************************************************************/
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);

  }




}


/*******************************************************************************
 * Function Name  : send_strip
 * Description    : Transmit 24 pulse to LED strip
 *                  
 * Input          : 24-bit data for the strip
 *                  
 * Output         : None
 * Return         : None
 *******************************************************************************/
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;
  }


  
}

/*******************************************************************************
 * Function Name  : reset_strip
 * Description    : Send reset pulse to reset all color of the strip
 *                  
 * Input          : None
 *                  
 * Output         : None
 * Return         : None
 *******************************************************************************/
void reset_strip()
{
  DATA_0;
  delayMicroseconds(20);
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 610
Posts: 49040
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This
Code:
void send_strip(uint32_t data)
{
  int i;
  unsigned long j=0x800000;
  
 
  for (i=0;i<24;i++)
  {
    if (data & j)
    {
      DATA_1;
is invoking the macro #defined at the top:
Code:
#define DATA_1 (PORTC |=  0X01)    // DATA 1    // for UNO
which is doing direct port manipulation on PORTC.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I see it calls it, but from what I see after it calls DATA_1 it's not passing any data to it

EDIT: is it set up so that everything between DATA_1 and DATA_0 is the data that's passed? I still only see sequences of "__asm__("nop\n\t");" if that's the case.. it doesn't look like the 'data' variable being passed into the function is ever sent to the pin o_O
« Last Edit: October 27, 2012, 09:40:23 am by soryazlawl » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 610
Posts: 49040
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
it doesn't look like the 'data' variable being passed into the function is ever sent to the pin o_O
Yes, it is, because the value of a bit in the data variable is used to determine whether to call DATA_1 or DATA_0.

The DATA_1 and DATA_0 macros diddle specific pins on the port.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm assuming the __asm__(); is a function that sends data to the port?

And this led strip is probably sent data through rapid successions of "__asm__("nop\n\t");"

Is there any good way of monitoring what's being sent out of my pins so I can check my theory? I've tried simply placing serial.println() in the sendstrip functions and it won't output anything and stops the functionality of the led strip D:
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm assuming the __asm__(); is a function that sends data to the port?

no, __asm__ means "I'm using C(++) in this file, but insert this section of assembly language." Assembly language is much lower level language, where every lline corresponds to one thing the microcontroller does.

nop in assembly means "Don't do anything for one clock cycle." So it's a good way to get really really tiny delays (it's like a call to the theoretical delay(62.5 nanoseconds) if you're running an arduino uno. If you have another CPU or another clock speed, it willl be a different time.)
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hmmm thank you, that makes sense. destroys my only theory as to how this program outputs data (and more importantly, what sort of data I should be passing to this led strip)

I've done quite a few ventures into programming before but this sketch is really throwing me for a loop
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 610
Posts: 49040
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The pin is being set using direct port manipulation. The register that contains the pin states for a given port is called PORTC. The DATA_1 and DATA_0 macros are diddling one pin in that port.
Logged

Valencia, Spain
Offline Offline
Faraday Member
**
Karma: 145
Posts: 5457
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The line you want is:

PORTC |=  0X01;

The i/O ports are memory mapped - they act just like a memory location. "PORTC" is defined as a pointer to that location somewhere in the Arduino header files.


Logged

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

Pages: [1]   Go Up
Jump to: