Copying data from one array to another over time - Page 1
Forum section: electronics / beginners

author: PeterFW
author_rank: Frequent Contributor
timestamp: January 19, 2016, 11:07:57 pm
content: Hello!I need a pointer in the right direction, since i have no clue how i could tackle this problem. I have a monochromatic LED matrix, each pixel with 8 bit resolution.The array is filled with random data and then displayed on the matix.Now i would like to load the next "frame" again with random data but slowly fade over from one frame to the other so i have a smooth transition.The speed of the change i would like to control, wich means, how fast it fades over.Alltough i can program the whole thing to do what i want so far, the slow fade is outside what my brain can handle to program.Greetings,Peter

author: psteichen
author_rank: Contributor
timestamp: January 19, 2016, 11:15:47 pm
content: Can you just put a delay in your code of time X, and then adjust X prior to compile or during execution to adjust the rate?

author: SL4P
author_rank: Super Contributor
timestamp: January 20, 2016, 02:02:35 am
content: The process is sometimes called in-betweening.As the display is monochrome (B+W), this may be difficult, but if you mean grayscale - it gets easier!(edited!)Basically go back to your high-school maths 'difference over time'Subtract the target value from the starting value to get a difference... then divide that by the number of steps (seconds / milliseconds etc)... to get the divisor, and when you're ready--Start bumping the current brightness +/- by the difference over 'divisor' number of steps.Check for over and underflow etc, but that's trivial once you've got the game running.This also works for RGB colour mixing, but may need more attention to gamma curves for colour linearity..

author: Brumby
author_rank: Unknown
timestamp: January 20, 2016, 04:46:04 am
content: WhatSL4Psaid.The only thing to note is that you should do your intermediate calculations using floating point and only revert back to integer when you physically assign the new pixel value to the pixel.

author: SL4P
author_rank: Super Contributor
timestamp: January 20, 2016, 04:57:22 am
content: Quote from: Brumby on January 20, 2016, 04:46:04 amA really good point.If your processor can support it, some interpolation applications will let you shift the values left a few bits, do the math as long-ints, then bump them back to the right again (loss of LSbits not so important). The performance improvement of long ints may not be visible - but will certainly not hit you as hard as floats... unless really necessary.

author: Brumby
author_rank: Unknown
timestamp: January 20, 2016, 05:06:22 am
content: Yes, that could work, but just make sure you have sufficient resolution - especially for long fades.

author: JacquesBBB
author_rank: Frequent Contributor
timestamp: January 20, 2016, 05:30:03 am
content: Suppose you want to go from X to Y in N steps.for k = 1 to NXk = ( k * Y + (N -k) X)/NPlot(Xk)All in integers.

author: Brumby
author_rank: Unknown
timestamp: January 20, 2016, 07:11:29 am
content: Quote from: JacquesBBB on January 20, 2016, 05:30:03 amYep - that works too. Just make sure you don't overflow on any intermediate results.

author: pmbrunelle
author_rank: Regular Contributor
timestamp: January 20, 2016, 09:12:07 am
content: Quote from: SL4P on January 20, 2016, 04:57:22 amI added a detail to that procedure in bold.

author: JacquesBBB
author_rank: Frequent Contributor
timestamp: January 20, 2016, 09:23:51 am
content: Quote from: Brumby on January 20, 2016, 07:11:29 amThere should be no problem. X, Y are 8 bits (uint8_t).If N is lower than 256, which is already huge, uint16_t (short ints) will be sufficient for intermediary results.The minimal complete line should then be (assuming X, Y, k, N are uint8_t) :Xk = (uint8_t) (( k * (uint16_t)Y + (N -k)(uint16_t) X)/N)

author: Brumby
author_rank: Unknown
timestamp: January 20, 2016, 02:37:12 pm
content: By specifying the data size, you have addressed the concern .... but there is still a danger with what you said here:Quote from: JacquesBBB on January 20, 2016, 09:23:51 amFirstly is the "IF". Offering a value of 256 is pure speculation and there is no indication that remotely suggests such a value is 'huge'. There is nothing to indicate that the OP will be limiting the number of steps to any given range. The reason for this is simple - the value N has nothing whatsoever to do with the intensity resolution of the LEDs, but is entirely and completely tied to the number of iterations his cross-fade routine will execute. If he has a fast processor, efficiently programmed and wants to make a very long fade, then the value of N could easily get into the thousands or even tens of thousands.If the value of 'N' is 257 or more, uint16_t won't cut it. I would suggest uint32_t to be safe(r).

author: JacquesBBB
author_rank: Frequent Contributor
timestamp: January 20, 2016, 03:48:05 pm
content: N is the number of steps in the transitions. I do not think that it should be linked to the duration of these stepsand so on the duration of the fade.The duration of each step is D (the total duration of the fade will be nearly N*D ) and it could be programmed asfor k = 1 to NXk = (uint8_t) (( k * (uint16_t)Y + (N -k)(uint16_t) X)/N)Plot(Xk)wait (D) // or use the CPU in a more useful mannerLike that, the length of the fade is not related to the speed of the CPU, and the CPU can do something else during the fade.

author: Brumby
author_rank: Unknown
timestamp: January 21, 2016, 01:15:37 am
content: If the objective at this stage of development is to just get the cross fade working - which it would seem is clearly obvious - then the coding will likely be a very basic loop. In this situation, the loop duration and, therefore, number of steps will be relevant.The needs of the system and the skills of the programmer will dictate the final coding. We can only guess at what considerations may or may not be needed - so I am just pointing out some of the hidden problems that should be addressed along the way.From the replies to date, I think the OP should have a fair idea of how to do it now.

author: Buriedcode
author_rank: Super Contributor
timestamp: January 21, 2016, 07:35:05 pm
content: I think we need to know what MCU/device you're using, as that will determine restrictions on mathematical capability (hardware division/multiplication, and how many instruction cycles between frames etc.).As others have already come up with the equations to help you along, I'll go down the simpler route assuming you're using an 8-bit device that runs at lower speed, say 8Mhz. I could of course be completely wrong with this assumption but its just in-case the previous answers went over your head or you're still stuck.Ok so, you have two arrays, each one containing random data. You wish to make your LED matrix 'blend' between these two arrays. First of all, you need to know how often you are updating the display - how long it takes to refresh the display from the frame buffer (your array). As others have stated, for each entry in the array (pixel) you find the difference between the current frame (first array), and the next (second array). Then divide this by how many 'steps' you want between the two patterns. I would start off small, and pick a number of steps that is a power of 2. This way, division simply becomes a matter of bit shifting (for MCU's that don't have hardware divide). 16 would be a good choice as this means you can just take the upper nibble (most micro's, AVR/PIC's have 'swap' which swaps nibbles).Now, some pixels will get dimmer, and some brighter, so some pixels will need to have a value subtracted, and some added, every step of the process. This means say the first pixel in the first frame was 240, and the first pixel in the second is 30, the difference is (second frame - first frame) = -210. Divided over 16 steps, thats -210/16 = -13. Every step the first pixel will have 13 subtracted from it. OR, as we're dealing with 8-bit integers, you can add (256-13) = 243. The implementation gets even more tricky if you use another array to store the 'difference'.I did have an 8-bit algorithm for this somewhere, written in C, but it only worked over 16/32/64 stages and wasn't particularly 'nice', although it only involved adding, subtracting, bit shifting and nibble swaps.Apologies for a bit of a ranty post, others have this covered, but it was just in case the OP was using an 8-bit processor with limited hardware maths.BC