IF comparisons too slow

James Ward

New Member
I am using a picaxe 40x2 at 64MHz to drive a 5x5x5 LED cube i made a few years ago but the problem is that the cube needs to have a high refresh rate so that the user does not perceive any flicker. However, i am using the get and put commands to store a map of 0s and 1s which shows which leds are on in each layer and then i have an if chain that turns on the corresponding LED. However, this if chain seems to be unbearably slow and i cannot find a reason for it other than that if commands must be slow on PICAXE. The first few leds light up very quickly as they are in the top layers of the if chain, however the further from the top of the elseif chain i get, the longer the led takes to light up until right at the end of even just one level there is about a 100ms delay in the led lighting up. Can anyone think of any way in which i could speed this up? The led cube works via multiplexing and thus to power an led it powers the layer and column that the led is in (it is also useful to note that for the columns, C1 C2 etc, low is on and high is off whereas for the layers, L1 L2 etc, high is on and low is off)

here's my code:
Code:
RENDER:
	for b0 = 0 to 124
		'debug
		let b1 = b0 % 25
		if b1 = 0 then gosub DEACTIVATE_ALL
		
		get b0,b1
		
		if b1 = 1 then
			if b0 >= 100 then
				high L5
			elseif b0 >= 75 then
				high L4
			elseif b0 >= 50 then
				high L3
			elseif b0 >= 25 then
				high L2
			else
				high L1
			endif
			
			b2 = b0 % 25
		
			if b2 = 0 then
				low C1
			elseif b2 = 1 then
				low C2
			elseif b2 = 2 then
				low C3
			elseif b2 = 3 then
				low C4
			elseif b2 = 4 then
				low C5
			elseif b2 = 5 then
				low C6
			elseif b2 = 6 then
				low C7
			elseif b2 = 7 then
				low C8
			elseif b2 = 8 then
				low C9
			elseif b2 = 9 then
				low C10
			elseif b2 = 10 then
				low C11
			elseif b2 = 11 then
				low C12
			elseif b2 = 12 then
				low C13
			elseif b2 = 13 then
				low C14
			elseif b2 = 14 then
				low C15
			elseif b2 = 15 then
				low C16
			elseif b2 = 16 then
				low C17
			elseif b2 = 17 then
				low C18
			elseif b2 = 18 then
				low C19
			elseif b2 = 19 then
				low C20
			elseif b2 = 20 then
				low C21
			elseif b2 = 21 then
				low C22
			elseif b2 = 22 then
				low C23
			elseif b2 = 23 then
				low C24
			elseif b2 = 24 then
				low C25

			endif
		endif
		
		'PAUSE 1
		
	next

	return
so in this code, the line:

elseif b2 = 24 then
low C25

takes about 100ms to be first called from when the loop is started. this is unacceptable as for the persistence of vision effect to be visible this needs to be at most 7 ms.
 

hippy

Technical Support
Staff member
Execution time does add up as you have seen, minimising execution time is critical for things like LED multiplexing, so "optimisation" is the word of the day for that.

One option instead of a series of IF-ELSEIF is to use a LOOKUP, for example ...

Code:
			if b2 = 0 then
				low C1
			elseif b2 = 1 then
				low C2
			elseif b2 = 2 then
				low C3
			elseif b2 = 3 then
				low C4
Could become -

Code:
LookUp b2, ( C1, C2, C3, C4 ... ), b9
Low b9
And that could be made quicker by using an EEPROM lookup table ...

Code:
Eeprom 0, ( C1, C2, C3, C4 ... )

Read b2, b9
Low b9
 

lbenson

Senior Member
How are C1 through C25 defined? I assume they are pin numbers. On the 40X2, pin B.0 has the value, 0, C.0 is 8, A.0 is 16, and D.0 is 24 (and D.7 is 31). Running the following line in simulation will show this: sertxd(#A.0,",",#B.0,",",#C.0,",",#D.0,cr,lf)

You can store the values of C1 through C25 in eeprom, and then use b2 as an index to retrieve the proper pin value.

For instance, the following program run in simulation illustrates this. Your own values for C1 through C25 should be in the EEPROM statement.

Code:
#picaxe 40X2
symbol rannum=w27
rannum=48611 ' some large prime
EEPROM 0,(C.0,C.1,C.2,C.3,C.4,C.5,C.6,C.7,B.0,B.1,B.2,B.3,B.4,B.5,B.6,B.7,A.0,A.1,D.0,D.1,D.2,D.3,D.4,D.5,D.6)
do
  low b4 
  random rannum
  b2 = rannum // 24
  read b2,b4
  high b4
  pause 1000
loop
(Hippy beat me to it.)
 

MartinM57

Moderator
(and you both beat me...)
...if there is, or could be, a mathematical relationship between b2 and the Cxx symbols, then using lbenson's variables:

Code:
b4 = some mathematical manipulation of b2
high b4
by the way

Code:
A.0 = Logical pin 16
A.1 = Logical pin 17
A.2 = Logical pin 18
A.3 = Logical pin 19
A.4 = Logical pin 20
A.5 = Logical pin 21
A.6 = Logical pin 22
A.7 = Logical pin 23
B.0 = Logical pin 0
B.1 = Logical pin 1
B.2 = Logical pin 2
B.3 = Logical pin 3
B.4 = Logical pin 4
B.5 = Logical pin 5
B.6 = Logical pin 6
B.7 = Logical pin 7
C.0 = Logical pin 8
C.1 = Logical pin 9
C.2 = Logical pin 10
C.3 = Logical pin 11
C.4 = Logical pin 12
C.5 = Logical pin 13
C.6 = Logical pin 14
C.7 = Logical pin 15
D.0 = Logical pin 24
D.1 = Logical pin 25
D.2 = Logical pin 26
D.3 = Logical pin 27
D.4 = Logical pin 28
D.5 = Logical pin 29
D.6 = Logical pin 30
D.7 = Logical pin 31
 

oracacle

Senior Member
I would be very tempted to rewire (if/were possible) for each value to match the logical pins and were not wire them as martinM75 suggests with a mathematical relationship.
I did this when I built the digital analogue clock, although based on Charlie plexing each of the LEDs has pin addresses for there function and they were stored in memory. a short algorithm calculated the addresses based on the time. seconds was a direct match, minutes was minutes +120 and hour was hour *5+120. the ptr was used to access that address directly.
 

MartinM57

Moderator
I think I'm understanding but there seems to an excess "were" in the first sentence?

My mathematical relationship might/should be very simple (and may take some wiring to achieve!) but it could be
b4 = b2 -1
b4 = 2 * b2 -1
etc
...or even the "null function"
b4 = b2 :)
 

AllyCat

Senior Member
Hi,

this IF chain seems to be unbearably slow and i cannot find a reason for it other than that IF commands must be slow on PICAXE.
Yes, the PICaxe interpreter is very slow for this type of application, up to 400 times slower than Assembler or optimised compiled code. But considerable improvements could be made, even with a similar structure. Hippy's LOOKUP method is probably about twice as fast as IF... ELSE, and an ON ... GOTO about the same improvement again. Another possibility is a "binary tree" structure: Personally I prefer to use IF ... GOTOs (beause it's easier to predict the timing delays), but I believe the equivalent "structured" format would be :
Code:
if b2 < 8 then
  if b2 < 4 then
    if b2 < 2 then
      if b2 < 1 then
        low 1
      else low 2
     else 
       if b2 < 3 then
         low 3
       else
          low 4
   else
      if b2 < 6
;    etc.
But for good speed, the program probably needs to be totally restructured to use address lookup tables and "parallel" data (e.g. pinsc = @bptr). PICaxe can often process complete bytes (and sometimes even words of 16 bits) as fast as single bits. But beware that some word operations can be 3 or 4 times slower than for an individual byte, so need to be checked.

A 5 x 5 x 5 array, which you appear to have structured as 5 x 25, is rather "inconvenient" in binary terms. For example, it might be worth considering an internal memory array of 16 x 8 (e.g 16 bytes in consecutive addresses) = 128 bits, and then "map" these to the 25 x 5 output pin array using a lookup table (in EPROM).

Cheers, Alan.
 
Top