Maker Pro
Maker Pro

Trouble with tribbles.. erm, timers.

The Hammer

Sep 17, 2013
164
Joined
Sep 17, 2013
Messages
164
I think this is being confused. You're saying exactly what I was saying about the refresh rate, but saying I had it wrong? The image I'm attaching is what I'm envisioning. Maybe you making an image would help if you don't agree?
per-led-png.13259
 

Attachments

  • per led.png
    per led.png
    114.2 KB · Views: 192

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
You have 18 columns. A column is updated every 1 ms.

That means the 18 columns take 18ms to update once (the entire array is scanned 55.55 times per second.

That also means that each individual column is updated 55.55 times per second.

Now, each column must be updated 20 times to allow the 20 brightnesses to be shown. So, if a single column is updated every 18ms, it will take 18 * 20 ms to update it 20 times. That's every 360 ms, or a little under 3 times per second.

If you're actually updating the entire array every 1ms, then you should be fine, but I don't think that's actually what you're doing.

edit: It doesn't matter if you scan the same column 20 times before moving on to the next, or scan the entire array 20 times. In both cases you'll see flashing. The nature of that flashing will differ, but you'll still have flashing.
 

The Hammer

Sep 17, 2013
164
Joined
Sep 17, 2013
Messages
164
Not much time to respond more right now, but each column should update at every 55.55 microseconds. That is my intent.

I think that when dealing with seconds you need to divide instead of multiply, but with Hz it's multiplying.

Why would I still see it though?? I don't understand. :(
 

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
Not much time to respond more right now, but each column should update at every 55.55 microseconds. That is my intent.

55 microseconds between updates for a single column means 18,000 times per second. Which means you're updating 18,000 * 18 columns every second (324,000 per second) or one every 3 millionths of a second.

I think that when dealing with seconds you need to divide instead of multiply, but with Hz it's multiplying.

With seconds you need to multiply, with frequency you need to divide.

Think of it this way. If your array gets larger, will things speed up or slow down? Imagine there are 1000 columns rather than 18. will it take 1000/18 times as long or 18/1000 times as long?

Why would I still see it though?? I don't understand. :(

The problem is that it's way too slow. If you allow 1/1000 of a second (1000 microseconds) for each column. It means that you're doing other columns for 17 x 1000us, so you only get back to that column every 18,000us, not 18,000 times per second.

What that means is that your entire array is effectively only getting updated around 3 times per second (because you need 20 scans of the entire array to go through a single PWM cycle. You will see a LED flashing 3 times per second, rather than a LED which appears to be dimly lit.
 

The Hammer

Sep 17, 2013
164
Joined
Sep 17, 2013
Messages
164
I don't think what you're saying makes much sense. I'm updating the entire array 1000 times a second. I had thought so anyway.. This is why I asked for an image if you disagreed. Visually, the image I made makes sense, and seems to agree with what I'm saying.
 
Last edited:

The Hammer

Sep 17, 2013
164
Joined
Sep 17, 2013
Messages
164
To be honest I'm not sure it matters... the code I'm running executes while TCNT0 == 31, which is a severe improvement, but won't run fast enough for what you're saying.. I'm starting to wonder if maybe using an MCU for this task wasn't a bad choice after all.. I guess I'd like to see how well the MCU operates while running off an 18MHz clock... need to find capacitors first.. otherwise I may have to move on to ARM 200MHz MCU..

Code:
/*
* GccApplication6.cpp
*
* Created: 5/23/2014 2:23:59 PM
*  Author: The Hammer
*/


#include <avr/io.h>

struct BPCStruct {
    uint8_t Value;
    uint8_t FadeTime;
};
struct BCStruct {
    uint8_t Value;
};
struct KeyStruct {
    uint8_t pressed;
    uint8_t fadestep;
    BCStruct BC[3];
    BPCStruct BPC[3];    // B, G, CC, R
};
KeyStruct key[108];
uint8_t brightstep = 0;
uint8_t ccathodes = 0;
uint8_t KEYn = 0;
uint8_t LEDc = 0;
void LEDanode ();
int main(void)
{
    DDRA = 0b11111111;
    PORTA = 0b11110000;
    DDRB = 0b00000000;
    PORTB = 0b11111111;
    TCCR0B |= (1 << CS01);
    brightstep = 0;
    ccathodes = 0;
    KEYn = 0;
    LEDc = 0;
    for (uint8_t ksv = 0; ksv < 108; ++ksv)
    {
        key[ksv].pressed = 0;
        key[ksv].fadestep = 0;
        key[ksv].BC[0].Value = 0;
        key[ksv].BC[1].Value = 0;
        key[ksv].BC[2].Value = 10;
        key[ksv].BPC[0].FadeTime = 0;
        key[ksv].BPC[1].FadeTime = 0;
        key[ksv].BPC[2].FadeTime = 0;
        key[ksv].BPC[0].Value = 10;
        key[ksv].BPC[1].Value = 0;
        key[ksv].BPC[2].Value = 0;
    }
    while(1)
    {
        if (1==1)
        {
            key[(TCNT0 - 30)].pressed = 1;
            TCNT0 = 0;                  //reset time counter
            PORTA |= (1 << PINA4);        //(set high) copy data out -latch- this outputs changes that are stored in both sets of shift registers
            PORTA &= ~(1 << PINA4);        //(set low)
            LEDc = 0;           //LED color 0
            LEDanode ();
            LEDc = 1;           //LED color 1
            LEDanode ();
            LEDc = 2;           //LED color 2
            LEDanode ();
            ++KEYn;                //--------------key 2 in this column
            LEDc = 0;           //LED color 0
            LEDanode ();
            LEDc = 1;           //LED color 1
            LEDanode ();
            LEDc = 2;           //LED color 2
            LEDanode ();
            ++KEYn;                //--------------key 3 in this column
            LEDc = 0;           //LED color 0
            LEDanode ();
            LEDc = 1;           //LED color 1
            LEDanode ();
            LEDc = 2;           //LED color 2
            LEDanode ();
            ++KEYn;                //--------------key 4 in this column
            LEDc = 0;           //LED color 0
            LEDanode ();
            LEDc = 1;           //LED color 1
            LEDanode ();
            LEDc = 2;           //LED color 2
            LEDanode ();
            ++KEYn;                //--------------key 5 in this column
            LEDc = 0;           //LED color 0
            LEDanode ();
            LEDc = 1;           //LED color 1
            LEDanode ();
            LEDc = 2;           //LED color 2
            LEDanode ();
            ++KEYn;             //--------------key 6 in this column
            LEDc = 0;           //LED color 0
            LEDanode ();
            LEDc = 1;           //LED color 1
            LEDanode ();
            LEDc = 2;           //LED color 2
            LEDanode ();
            if (KEYn == 107)    //--------------key 1 in next column
                KEYn = 0;
            else
                ++KEYn;
            //--end anodes----------------------begin cathodes--
            if (!ccathodes)        //adjust which common cathode set is active
            {
                ccathodes = 17;
                PORTA |= (1 << PA2);    //cathodes' data (high)
                PORTA |= (1 << PA3);    //cathodes' sh_cp (high)
                PORTA &= ~(1 << PA3);   //cathodes' sh_cp (low)
                PORTA &= ~(1 << PA2);   //cathodes' data (low)
                if (brightstep == 19)   //adjust current brightness step
                    brightstep = 0;
                else
                    ++brightstep;
            }
            else
            {
                --ccathodes;
                PORTA |= (1 << PA3);    //cathodes' sh_cp (high)
                PORTA &= ~(1 << PA3);   //cathodes' sh_cp (low)
            }
        }
        /*else
        {
            for (uint8_t cks = 6; cks > 3; cks--)
            {
                if (cks == 6)
                {
                    PORTA &= ~(1 << 6);
                    for (uint8_t ckp = 0; ckp < 8; ckp++)
                    {
                        if (!(PINB & (1 << ckp)))
                        key[ckp].pressed = 1;
                        else if (key[ckp].pressed)
                        key[ckp].pressed = 0;
                    }
                    PORTA |= (1 << 6);
                }
                else if (cks == 5)
                {
                    PORTA &= ~(1 << 5);
                    for (uint8_t ckp = 0; ckp < 8; ckp++)
                    {
                        if (!(PINB & (1 << ckp)))
                        key[(ckp + 8)].pressed = 1;
                        else if (key[(ckp + 8)].pressed)
                        key[(ckp + 8)].pressed = 0;
                    }
                    PORTA |= (1 << 5);
                }
                else if (cks == 4)
                {
                    PORTA &= ~(1 << 4);
                    for (uint8_t ckp = 0; ckp < 8; ckp++)
                    {
                        if (!(PINB & (1 << ckp)))
                        key[(ckp + 16)].pressed = 1;
                        else if (key[(ckp + 16)].pressed)
                        key[(ckp + 16)].pressed = 0;
                    }
                    PORTA |= (1 << 4);
                }
            }
        }*/
    }
}
void LEDanode ()
{
    if (key[KEYn].fadestep)
    {
        if (brightstep < key[KEYn].BPC[LEDc].FadeTime)            //set the anode on the shift registers
            PORTA |= (1 << PA0);
        else
            PORTA &= ~(1 << PA0);
        if (brightstep == 19)
        {
            --key[KEYn].fadestep;
            if (key[KEYn].pressed)                //if this key is pressed
            {
                key[KEYn].fadestep = 50;
                key[KEYn].BPC[LEDc].FadeTime = key[KEYn].BPC[LEDc].Value;
            }
            else if (key[KEYn].BPC[LEDc].Value > key[KEYn].BC[LEDc].Value)
                key[KEYn].BPC[LEDc].FadeTime = key[KEYn].BC[LEDc].Value - (((key[KEYn].BC[LEDc].Value - key[KEYn].BPC[LEDc].Value) / 50) * key[KEYn].fadestep);
            else if (key[KEYn].BPC[LEDc].Value < key[KEYn].BC[LEDc].Value)
                key[KEYn].BPC[LEDc].FadeTime = ((key[KEYn].BC[LEDc].Value - key[KEYn].BPC[LEDc].Value) / 50) * key[KEYn].fadestep;
            else
                key[KEYn].fadestep = 0;
        }
    }
    else
    {
        if (brightstep < key[KEYn].BC[LEDc].Value)            //set the anode on the shift registers
            PORTA |= (1 << PA0);
        else
            PORTA &= ~(1 << PA0);
        if (key[KEYn].pressed && brightstep == 19)
        {
            key[KEYn].fadestep = 50;
            key[KEYn].BPC[LEDc].FadeTime = key[KEYn].BPC[LEDc].Value;
        }
    }
    PORTA |= (1 << PINA1);                            //(set high) shift data in-clock
    PORTA &= ~(1 << PINA1);                            //(set low)
}
 

The Hammer

Sep 17, 2013
164
Joined
Sep 17, 2013
Messages
164
Excuse me, an AVR, not an MCU.. fat fingers late at night since I'm not typing on the keyboard I'm developing yet. :p
 

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
TO scan the display you need to do 1 column, pause, do the next column, pause, the next column, pause... And all the pauses have to be the same duration or some columns will appear brighter than others.

What is the duration of that pause? (I thought it was 1 ms, but if it's less then it's something I've misunderstood)
 

The Hammer

Sep 17, 2013
164
Joined
Sep 17, 2013
Messages
164
Why do I have to do it that way? What's wrong with the way I depicted it in my image where it's broken up more complex?
 

Solidus

Jun 19, 2011
349
Joined
Jun 19, 2011
Messages
349
It'll take me some time to go through all this as I'm fried in the head from being under the gun with iOS app development, so this won't address the logistical issues here as much as "more organizational" coding practices.

Visualize this project as a stack or nest system of different layers.

At the lowest level, you have your LED array management - so scanning and what-not.
Next highest, you have your basic fill/fade operations - filling the keyboard or a certain portion with a desired color and then transitioning to another.
Higher than that, you have your high-level routines - how the keys "react" in color terms to broad-scope software states.
At the highest-level, you have your key handler - how the system MCU will react to key presses. These are the highest level because these are interrupt-driven; the system will only process them via an ISR when they occur and otherwise could not care less about them.

What you should do is have scanning functions that call out of a buffer, suppose a buffer of structs or hell, a custom object. This would work similarly to a frame buffer in a video card. You then write a color fill function which allows you to fill any particular key with a color and flush it to the frame buffer for the next scan - i.e., like putting a single blue key on a field of red.

Code:
typedef struct buffer_struct
{
    int led;
    char red;
    char grn;
    char blu;
} Buffer;

struct Point
{
    int x;
    int y;
}

class Driver
{
    public:
    Buffer [][] buf;
    bool flushBufferAndScan(void);
    void fillForPoint(Point p);
    void clearBuffer(void);
    // ...etc.
}

Once you have that written, you have an internal "driver" for the array that takes care of all such handling for you. You can then write extensible functions on top of that layer that add your higher-level functionality. If you had a sizeable-enough array and a large enough buffer, you could even extend the fill/scan function dimer to allow for primitive bitmap rendering.

The issue I see here is one that will persist regardless of timing quirks being ironed out; it's that if you don't make the lowest level extensible or able to "stretch" to your coding additions, then you're going to throw ten fits every time you want a new color mode because you're having to rewrite the lowest driving layer.

Take it from experience - the iOS app I'm about to publish was begun when I knew nothing about Objective-C, the language in question, and much less about programming in general or what was considered "good" programming practice. The code I wrote early on was so application-specific that I wouldn't be able to add features to the app in the future without completely scratching out the lower, early codebases and rewriting them.

Struggling with the lower-level stuff just a tad bit more will save tons of heartache and wall-beating later on when your additions at one level are reliant on another.
 
Last edited:

The Hammer

Sep 17, 2013
164
Joined
Sep 17, 2013
Messages
164
Hmmm, food for thought, and while I'm not disagreeing with the methodology.. it seems like what you're talking about is just adding processing time when the code I've written is absolutely not working fast enough as is! I even moved over to using an 18MHz crystal for the clock source.. I'm going to try to alter my code to do it in the order you're talking about, but I just don't see it working fast enough..
 

The Hammer

Sep 17, 2013
164
Joined
Sep 17, 2013
Messages
164
Yup, at least I tried the most effecient way I could think of to deal with it the way you guys were suggesting, and it takes even longer to process.. plus, now the blinking is far more noticeable from the gaps of the entire array being off while one column processes 20 brightness steps. The ghosting issues we were talking about got even worse with this method as well.. at least the 6th LED is ghosting from the 1st, but none of the others are (WTF??).

Code:
/*
* GccApplication6.cpp
*
* Created: 5/23/2014 2:23:59 PM
*  Author: The Hammer
*/


#include <avr/io.h>

struct BPCStruct {
    uint8_t Value;
    uint8_t FadeTime;
};
struct BCStruct {
    uint8_t Value;
};
struct KeyStruct {
    uint8_t pressed;
    uint8_t fadestep;
    BCStruct BC[3];
    BPCStruct BPC[3];    // B, G, CC, R
};
KeyStruct key[108];
uint8_t tcntct = 0;
uint8_t brightstep = 0;
uint8_t KEYn = 101;
uint8_t LEDc = 0;
void PerformRow ();
void LEDanode ();
int main(void)
{
    DDRA = 0b11111111;
    PORTA = 0b00000000;
    DDRB = 0b00000000;
    PORTB = 0b11111111;
    TCCR0B |= (1 << CS01);
    brightstep = 0;
    KEYn = 0;
    LEDc = 0;
    for (uint8_t ksv = 0; ksv < 108; ++ksv)
    {
        key[ksv].pressed = 0;
        key[ksv].fadestep = 0;
        key[ksv].BC[0].Value = 0;
        key[ksv].BC[1].Value = 0;
        key[ksv].BC[2].Value = 10;
        key[ksv].BPC[0].FadeTime = 0;
        key[ksv].BPC[1].FadeTime = 0;
        key[ksv].BPC[2].FadeTime = 0;
        key[ksv].BPC[0].Value = 15;
        key[ksv].BPC[1].Value = 20;
        key[ksv].BPC[2].Value = 10;
    }
    PORTA |= (1 << PA2);    //cathodes' data (high)
    PORTA |= (1 << PA3);    //cathodes' sh_cp (high)
    PORTA &= ~(1 << PA3);    //cathodes' sh_cp (low)
    PORTA &= ~(1 << PA2);    //cathodes' data (low)
    //key[0].pressed = 1;
    key[0].pressed = 1;
    while(1)
    {
        if (124 <= TCNT0)
        {
            TCNT0 = 0;            //reset time counter
            PORTA |= (1 << PINA4);        //(set high) copy data out -latch- this outputs changes that are stored in both sets of shift registers
            PORTA &= ~(1 << PINA4);        //(set low)
            PerformRow ();
            if (brightstep == 19)    //adjust current brightness step
            {
                brightstep = 0;
                switch (KEYn)
                {
                    case 102:
                        PORTA |= (1 << PA2);    //cathodes' data (high)
                        PORTA |= (1 << PA3);    //cathodes' sh_cp (high)
                        PORTA &= ~(1 << PA3);    //cathodes' sh_cp (low)
                        PORTA &= ~(1 << PA2);    //cathodes' data (low)
                        KEYn = 0;
                        break;
                    default:
                        KEYn += 6;
                        PORTA |= (1 << PA3);    //cathodes' sh_cp (high)
                        PORTA &= ~(1 << PA3);    //cathodes' sh_cp (low)
                        break;
                }
            }
            else
                ++brightstep;
        }
        /*else
        {
            for (uint8_t cks = 6; cks > 3; cks--)
            {
                if (cks == 6)
                {
                    PORTA &= ~(1 << 6);
                    for (uint8_t ckp = 0; ckp < 8; ckp++)
                    {
                        if (!(PINB & (1 << ckp)))
                        key[ckp].pressed = 1;
                        else if (key[ckp].pressed)
                        key[ckp].pressed = 0;
                    }
                    PORTA |= (1 << 6);
                }
                else if (cks == 5)
                {
                    PORTA &= ~(1 << 5);
                    for (uint8_t ckp = 0; ckp < 8; ckp++)
                    {
                        if (!(PINB & (1 << ckp)))
                        key[(ckp + 8)].pressed = 1;
                        else if (key[(ckp + 8)].pressed)
                        key[(ckp + 8)].pressed = 0;
                    }
                    PORTA |= (1 << 5);
                }
                else if (cks == 4)
                {
                    PORTA &= ~(1 << 4);
                    for (uint8_t ckp = 0; ckp < 8; ckp++)
                    {
                        if (!(PINB & (1 << ckp)))
                        key[(ckp + 16)].pressed = 1;
                        else if (key[(ckp + 16)].pressed)
                        key[(ckp + 16)].pressed = 0;
                    }
                    PORTA |= (1 << 4);
                }
            }
        }*/
    }
}
void PerformRow ()
{
    LEDc = 0;            //LED color 0
    LEDanode ();
    LEDc = 1;            //LED color 1
    LEDanode ();
    LEDc = 2;            //LED color 2
    LEDanode ();
    ++KEYn;                //--------------key 2 in this column
    LEDc = 0;            //LED color 0
    LEDanode ();
    LEDc = 1;            //LED color 1
    LEDanode ();
    LEDc = 2;            //LED color 2
    LEDanode ();
    ++KEYn;                //--------------key 3 in this column
    LEDc = 0;            //LED color 0
    LEDanode ();
    LEDc = 1;            //LED color 1
    LEDanode ();
    LEDc = 2;            //LED color 2
    LEDanode ();
    ++KEYn;                //--------------key 4 in this column
    LEDc = 0;            //LED color 0
    LEDanode ();
    LEDc = 1;            //LED color 1
    LEDanode ();
    LEDc = 2;            //LED color 2
    LEDanode ();
    ++KEYn;                //--------------key 5 in this column
    LEDc = 0;            //LED color 0
    LEDanode ();
    LEDc = 1;            //LED color 1
    LEDanode ();
    LEDc = 2;            //LED color 2
    LEDanode ();
    ++KEYn;             //--------------key 6 in this column
    LEDc = 0;            //LED color 0
    LEDanode ();
    LEDc = 1;            //LED color 1
    LEDanode ();
    LEDc = 2;            //LED color 2
    LEDanode ();
    KEYn -= 5;
}
void LEDanode ()
{
    if (key[KEYn].fadestep)
    {
        if (brightstep < key[KEYn].BPC[LEDc].FadeTime)            //set the anode on the shift registers
            PORTA |= (1 << PA0);
        else
            PORTA &= ~(1 << PA0);
        if (brightstep == 19)
        {
            --key[KEYn].fadestep;
            if (key[KEYn].pressed)                //if this key is pressed
            {
                key[KEYn].fadestep = 50;
                key[KEYn].BPC[LEDc].FadeTime = key[KEYn].BPC[LEDc].Value;
            }
            else if (key[KEYn].BPC[LEDc].Value > key[KEYn].BC[LEDc].Value)
                key[KEYn].BPC[LEDc].FadeTime = key[KEYn].BC[LEDc].Value - (((key[KEYn].BC[LEDc].Value - key[KEYn].BPC[LEDc].Value) / 50) * key[KEYn].fadestep);
            else if (key[KEYn].BPC[LEDc].Value < key[KEYn].BC[LEDc].Value)
                key[KEYn].BPC[LEDc].FadeTime = ((key[KEYn].BC[LEDc].Value - key[KEYn].BPC[LEDc].Value) / 50) * key[KEYn].fadestep;
            else
                key[KEYn].fadestep = 0;
        }
    }
    else
    {
        if (brightstep < key[KEYn].BC[LEDc].Value)            //set the anode on the shift registers
            PORTA |= (1 << PA0);
        else
            PORTA &= ~(1 << PA0);
        if (key[KEYn].pressed && brightstep == 19)
        {
            key[KEYn].fadestep = 50;
            key[KEYn].BPC[LEDc].FadeTime = key[KEYn].BPC[LEDc].Value;
        }
    }
    PORTA |= (1 << PINA1);                            //(set high) shift data in-clock
    PORTA &= ~(1 << PINA1);                            //(set low)
}
 
Last edited:

The Hammer

Sep 17, 2013
164
Joined
Sep 17, 2013
Messages
164
With the buffer idea you were posting.. are you saying that essentially I should be making an array of 20 bools (for instance) where if a key's normal intensity is 10 then key[?].BC[?].intensity[9] would be true, where key[?].BC[?].intensity[10] would be false? This seems like it would cost significant amounts of RAM for the additional speed boost.. not even that great of a speed boost I would think.
 
Last edited:

Solidus

Jun 19, 2011
349
Joined
Jun 19, 2011
Messages
349
It's not going to add that much processing time, and the modularization of the code is only going to make your life easier when it comes to debugging, i.e. here.

Not only does it allow you to add functions with ease because you already have a programmatic layer to abstract on, but it also means you don't have to scrutinize your whole code body when an error in one part occurs. I don't see how it is adding processing time. Calling everything in a single shot may make the code run "faster" because your brain can intuitively process it as a single block, but modularizing it into a bunch of sub-functions ideally shouldn't make it any slower aside from branching subcalls (which are usually single-cycle) provided the code is of the same level of optimization.

If a timing error occurs, adjust the layer that deals with the timing (the driving layer).
If a color/pattern error occurs, adjust the higher-level layer (the patterning layer).
If a key event error occurs, adjust the key handler.

Modular code improves the debug capability. If it's a one-off sort of project (I write these sorts of things to write dictionary files for my apps), throwing everything in a medley in a int main "pot" works. For code you think you'll be wanting to add to later or that you anticipate any sort of error in, you'll be shooting yourself in the foot without subclassing out functionality to individual delegates.

RAM is not an issue. You're creating 108 instances of KeyStruct which are 11 bytes each. That's over a kB. If you really want to micromanage, you can use pointers to avoid having to explicitly declare an array of bools or uint8_t provided the memory ranging is contiguous.

Get me the board-specific pinouts and I'll see what I can whip up.
 

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
Can you post just the code which controls the timing of the scanning of your array.
 

The Hammer

Sep 17, 2013
164
Joined
Sep 17, 2013
Messages
164
Can you post just the code which controls the timing of the scanning of your array.
I already have. I posted the one where you suggested I do one column at a time for all 20 brightness levels, and I posted the one I originally made with where it does the entire array for one brightness level.
 
Last edited:

The Hammer

Sep 17, 2013
164
Joined
Sep 17, 2013
Messages
164
It's not going to add that much processing time, and the modularization of the code is only going to make your life easier when it comes to debugging, i.e. here.
It does add some, and the faster less desirable way it was designed was still not as fast as I needed it to be.

Not only does it allow you to add functions with ease because you already have a programmatic layer to abstract on, but it also means you don't have to scrutinize your whole code body when an error in one part occurs. I don't see how it is adding processing time. Calling everything in a single shot may make the code run "faster" because your brain can intuitively process it as a single block, but modularizing it into a bunch of sub-functions ideally shouldn't make it any slower aside from branching subcalls (which are usually single-cycle) provided the code is of the same level of optimization.

If a timing error occurs, adjust the layer that deals with the timing (the driving layer).
If a color/pattern error occurs, adjust the higher-level layer (the patterning layer).
If a key event error occurs, adjust the key handler.

Modular code improves the debug capability. If it's a one-off sort of project (I write these sorts of things to write dictionary files for my apps), throwing everything in a medley in a int main "pot" works. For code you think you'll be wanting to add to later or that you anticipate any sort of error in, you'll be shooting yourself in the foot without subclassing out functionality to individual delegates.

RAM is not an issue. You're creating 108 instances of KeyStruct which are 11 bytes each. That's over a kB. If you really want to micromanage, you can use pointers to avoid having to explicitly declare an array of bools or uint8_t provided the memory ranging is contiguous.

Get me the board-specific pinouts and I'll see what I can whip up.
I'm not worried about the extra memory usage as it's there to be used, but questioning weather this is going to honestly solve the fact that it's just running too slow.

For right now I'm using these:
PA0 = data in for LED anodes
PA1 = clock/shift for LED anodes
PA2 = data in for LED cathodes
PA3 = clock/shift for LED cathodes
PA4 = latch/output memory to Q0-Q7 on all 74HC595

If you want me to change the hardware design, just advise me as to what you think would work.
 

(*steve*)

¡sǝpodᴉʇuɐ ǝɥʇ ɹɐǝɥd
Moderator
Jan 21, 2010
25,510
Joined
Jan 21, 2010
Messages
25,510
I already have. I posted the one where you suggested I do one column at a time for all 20 brightness levels, and I posted the one I originally made with where it does the entire array for one brightness level.

I'll check it out. Maybe I didn't quite get what you are doing.
 
Top