Help Please - Binary/Decimal Maths for I/O bit patterns

BCJKiwi

Senior Member
Hi, am in the search of speed and efficiency.
The following code (a part only of the whole project) achieves the process of reading the current value of a compass chip, and of an accelerometer chip.
These values are used to output via MCP23016 I/O expanders which are arranged in two banks of 8 so output of the LEDs to turn on is achieved by sending two bytes to the MCP23016 representing the bit patterns required.
Later they will also be logged to USB or SD storage.
Have refined the code which follows but feel it could be better.
Have already established that using 'lookup' saves substantial code space. The subroutine using lookup at the program end saves 184 bytes over the alternative If/Else/Endif construct.
However both the If/Else/Endif construct and the Lookup code rely on a list of symbol statements to represent the bit patterns.

It seems that the bit pattern should be able to be calculated directly rather than looking up the value from the list. However I feel this would probably require a number of If/Else/Endif statements anyway and as the bit patterns required are not as straight-forward as it initially appears it may not actually be a lot more efficient.

At this stage I can't figure the best way to do the math so am not sure if its worth proceeding any further.

So much Kudos to those who can offer up a better (i.e. faster and/or smaller) solution.

Here's the code - I trust it is sufficiently commented to to provide the needed info for analysis.

Thanks

Code:
'####################################################################################
'# PICAXE 28X1,  DIMENSION ENGINEERING  DEACCM3D,   MCP23016 I/O    #
'####################################################################################
#picaxe 28x1
SetFreq m8
'####################################################################################
symbol CMP_0 = %11000000 'Devantech CMPS03 i2c address
symbol IO_0  = %01000000  'Compass   - Microchip MCP23016 I/O expander i2c address
symbol IO_1  = %01000010  'Left/Right accelerometer
symbol IO_2  = %01000100  'Acceleration/Braking accelerometer
symbol IO_3  = %01000110  
symbol LC0   = %11111111  'compass binary data for 16 LED heading display
symbol LC1   = %11111110  'LC == Led Compass
symbol LC2   = %11111101  '16 values - 0 thru 15 represent 360 degrees of compass
symbol LC3   = %11111011  'Displayed by turning on 1 led of 16 
symbol LC4   = %11110111  ' on two banks of MCP23016 16 port I/O expander
symbol LC5   = %11101111
symbol LC6   = %11011111
symbol LC7   = %10111111
symbol LC8   = %01111111
'
symbol LA0 = %11111111  'Accelerometer binary data for LED Display
symbol LA1 = %11111110  'LA == Led Accelerometer
symbol LA2 = %11111100  '21 values - 0 thru 20 represent 0, and + 1 thru 10 & - 1 thru 10
symbol LA3 = %11111000  'Displayed by turning on LEDs of 10 led Bar graph
symbol LA4 = %11110000  'Leds turned on in bar graph mode - from left to right for +
symbol LA5 = %11100000  'Leds turned on in bar graph mode - from right to left for -
symbol LA6 = %11000000  'NO LEDs turned on at mid range (= value 10)
symbol LA7 = %10000000  '1 thru 8 on one bank of MCP23016 16 port I/O expander,
symbol LA8 = %00000000  '  2 leds on the other
'
symbol LA10 = %11111111  'Accelerometer binary data for LED Display
symbol LA11 = %11111101  'LA == Led Accelerometer
symbol LA12 = %11111100
symbol LA21 = %01111111
symbol LA22 = %00111111
symbol LA23 = %00011111
symbol LA24 = %00001111
symbol LA25 = %00000111
symbol LA26 = %00000011
symbol LA27 = %00000001
symbol LA28 = %00000000
Init:
'MCP23016
 hi2csetup i2cmaster,IO_0,i2cfast_8,i2cbyte
  '%0100 0  0  0  0 is the address with A0,A1,A2 all tied to 0V
  '%0100 A2 A1 A0 RW - there is no explanation for the 6th bit being '1'
  'If using multiple devices of different speeds on the bus,
  'then use this line to change speed and remove the [%01000000] in the next line.
 hi2cout [IO_0],6,($00,$00)
  'IRDIR0,IRDIR1 set port direction register to output
  'Note:- MCP23016 documentation indicates this register pair (06 & 07) 
  'defaults to all 1's (all Inputs) on Power On Reset.
  'However if this register pair is not configured to all 0's (Outputs)
  ' there is no function when driving LEDS.
 hi2cout $0A,($00,$00)  'IOCON0
 hi2cout 0,(LC0,LC0)  'turn off all the LEDs
 hi2cout [IO_1],6,($00,$00) 'IRDIR0,IRDIR1 set port direction register to output`
 hi2cout $0A,($00,$00)  'IOCON0  
 hi2cout 0,(LC0,LC0)  'turn off all the LEDs
 
Main: 
 
'COMPASS
Compass:
' hi2csetup i2cmaster,%11000000,i2cfast_8,i2cbyte ' Set up i2c for device
' hi2csetup i2cmaster,[CMP_0],i2cfast_8,i2cbyte ' Set up i2c for device
      'If using multiple devices of different speeds on the bus,
      'then use this line and remove the [CMP_0] in the next line.
' hi2cin [CMP_0],0,(b22)       'Read CMPS03 Software Revision
      '[CMP_0] ensures correct i2c is read - reqd if more than one 
      'i2c device on bus being read in sequence
 hi2cin [CMP_0],2,(b27,b26)   '(w13) Read compass bearing as a word (0-3599 for full circle)
        'CMPS03 Register 2=HighByte,3=LowByte.w13(b26)=hibyte,(b27)=Lobyte 
 ptr=4
 'Store w13 for datalogging; 0-3599
 'future datalogging code here
 If @ptr = b26 then EndCompass ' skip if MSB not changed
 @ptr=b26    ' store MSB (35) to Scratchpad 4
 inc ptr
 @ptr=b27    ' store LSB (99) to Scratchpad 5
 b0 = w13+113/225 ' add 113 (225/5) to offset zero to mid of 1/16 step,
    '  divide by 225 to get 16 values
 if w13 > 3485 then let b0 = 0'0 represents North, 0 - 15 and Centre result on zero degrees
 endif
 if b0 < 8 then let b20 = LC0
 lookup b0,(LC1,LC2,LC3,LC4,LC5,LC6,LC7,LC8),b21
 else
 let b21 = LC0
 b0=b0-8
 lookup b0,(LC1,LC2,LC3,LC4,LC5,LC6,LC7,LC8),b20
  endif
IOEXP_0:
  hi2cout [IO_0],0,(b21,b20)
' sertxd (" Compass Bearing:",#w13,"  ",#b0,cr,lf)
  EndCompass:
'ACCELEROMETER
ACCEL_0:
'Read value and store to scratchpad
' use to calibrate actual output from ACCM3D
 'sertxd ("X = ",#w0,"   Y = ",#w1) 
 'pause 10000    ' Current actual values == X = 333, Y = 340, Z = 398
'subtract 126 from X and Y values to obtain value for '0' - the min value.
'Divide by 12 to get 21 integers 0 thru 20
'range is 21 X 12 = 252 or 0 thru 251.
'Gives 10 leds for each direction plus no led for no g (1x10 led bar used on both directions)
IOEXP_1:      'Left / right Accelerometer
 ReadADC10 1, w0 'Dimension Engineering DE-ACCM3D Accelerometer +- 3G in X,Y & Z Axes
 b6=w0 Min 207 - 207 Max 251 / 12  'X - centre output on 126 (0g), limit to byte range (+-1.848G)
 ptr=1
 If @ptr = b6 then IOEXP_2  ' Skip if value not changed
 @ptr = b6     ' store X axis - scratchpad 1
 gosub Accel_Out
 hi2cout [IO_1],0,(b0,b1)  'Turn on LEDs output
 
IOEXP_2:      'Acceleration/Braking accelerometer
 ReadADC10 2, w1    '0g = 1.66V (ReadADC10 = 339) with 0.333v per g. 
       ' X & Y read 0g when level and static 
 b7=w1 Min 214 - 214 Max 251 / 12  'Y  - 1G = 68 units of ADC10 @ 5.0V Ref
 ptr=2
 If @ptr = b7 then ENDIOEXP 'IOEXP_3 ' Skip if value not changed
 @ptr = b7     ' store Y axis - scratchpad 2
 gosub Accel_Out
 hi2cout [IO_2],0,(b0,b1)  'Turn on LEDs output
 
'IOEXP_3:      'Vertical Accelerometer
' ReadADC10 3, w2    'Z Axis reads 1g when level and static
' b8=w2 Min 272 - 272 Max 251 / 12 'Z  - Correct Z Axis to centre output on 126 at 1g
' ptr=3
' If @ptr = b8 then ENDIOEXP ' Skip if value not changed
' @ptr = b8     ' store Z axis - scratchpad 3
' gosub Accel_Out
' hi2cout [IO_3],0,(b0,b1) 'Turn on LEDs output
ENDIOEXP:
Goto Main  'Loop for continuous display
'##############################################################################
'# SUBROUTINES           #
'##############################################################################
Accel_Out:
' Lookup code saves 184 bytes over If/Elseif sequence below
 If  @ptr = 10 then let b0 = LA0      'Led Number
  b1 = LA0         '10
 ElseIf @ptr > 10 and @ptr <13 then @ptr = @ptr-11
  lookup @ptr,(LA11,LA12),b1      '11 & 12
  let b0=LA10
 ElseIf @ptr > 1  and @ptr <10 then @ptr = @ptr-2
  lookup @ptr,(LA8,LA7,LA6,LA5,LA4,LA3,LA2,LA1),b0  '2 thru 9
  let b1=LA0
 ElseIf @ptr > 12 then @ptr = @ptr - 13
  lookup @ptr,(LA21,LA22,LA23,LA24,LA25,LA26,LA27,LA28),b0 '13 thru 20
  let b1=LA12
 else
  lookup @ptr,(LA2,LA1),b1      '0 & 1
  let b0=LA8
  endif
#rem
 If  @ptr = 10 AND @ptr <130 then let b0 = LA0 : let b1=LA0 'no output 0g == 125
 ElseIf @ptr = 9  then let b0 = LA1  : let b1=LA0 '9
 ElseIf @ptr = 8  then let b0 = LA2  : let b1=LA0 '8
 ElseIf @ptr = 11 then let b1 = LA11 : let b0=LA10 '11
 ElseIf @ptr = 12 then let b1 = LA12 : let b0=LA10 '12
 ElseIf @ptr = 7  then let b0 = LA3  : let b1=LA0 '7
 ElseIf @ptr = 13 then let b1 = LA12 : let b0=LA21 '13
 ElseIf @ptr = 6  then let b0 = LA4  : let b1=LA0 '6
 ElseIf @ptr = 14 then let b1 = LA12 : let b0=LA22 '14
 ElseIf @ptr = 5  then let b0 = LA5  : let b1=LA0 '5
 ElseIf @ptr = 15 then let b1 = LA12 : let b0=LA23 '15
 ElseIf @ptr = 4  then let b0 = LA6  : let b1=LA0 '4
 ElseIf @ptr = 16 then let b1 = LA12 : let b0=LA24 '16
 ElseIf @ptr = 3  then let b0 = LA7  : let b1=LA0 '3
 ElseIf @ptr = 17 then let b1 = LA12 : let b0=LA25 '17
 ElseIf @ptr = 2  then let b0 = LA8  : let b1=LA0 '2
 ElseIf @ptr = 18 then let b1 = LA12 : let b0=LA26 '18
 ElseIf @ptr = 1  then let b0 = LA8  : let b1=LA1 '1
 ElseIf @ptr = 19 then let b1 = LA12 : let b0=LA27 '19
 ElseIf @ptr = 0  then let b0 = LA8  : let b1=LA2 '0
 ElseIf @ptr = 20 then let b1 = LA12 : let b0=LA28 '20
 EndIf
#endrem
Return
Well its a pain that the formatting is not retained but this is too big to re-edit here - is there a way to retain the code formatting?
 
Last edited:

BCJKiwi

Senior Member
I have found in some testing in a separate code section that I can produce the bit patterns for;
LA0 thru LA8 symbols using Shift left,
LA21 thru LA28 with Shift left and REV 8
The walking bit '0' pattern for LC0 thru LC8 with shift left and add 1 in a loop
LA10 thru LA12 can be achieved by one or other of the above methods.

Have also found that the REV function wll not simulate but will run in the chip.

Will code it into the above program and test and post results (another day - its 1:30am right now!
 

hippy

Technical Support
Staff member
If you're after speed and efficiency ( but how is 'efficiency' measured ? ) you will probably want to do minimal calculations and use as much lookup and loading of constants as possible. Using Shifts and Rev will be far less speedy, a loop of shifts and adds is incredibly slower than just looking up the result.

For maximum speed of execution, you're heading in the wrong direction. For minimum code you want to calculate as much as possible, for maximum speed you want to do as little calculation, as few operations and unroll loops into sequentially repeating steps. Every extra loop and instruction extends time. The consequence is that fastest executing code can use up a lot more program space.

Lookups themselves are not particularly quick and you'd be far better off using Data/Eeprom commands and Read ...

- Lookup b0,("A","B","C"),b1

- Read b0,b1
- Eeprom 0,("A","B","C")

You need to adjust the 'b0' in Reads because not everything an be put at location zero in Data/Eeprom ut you should still see significant speed increases.
 

BCJKiwi

Senior Member
Hmmmm,
Hippy, I replied Last evening late NZ time thanking you for your input, and for the info on eeprom as I had overlooked that option.

The post seemed to have disappeared (or was not received). I was aware of the tradeoff of speed vs program size with simple vs complex instructions - just not sure of the effect and plan to do some testing.

However until one finds the most elegant formula then you don't know how complex it will be!
 
Last edited:

BCJKiwi

Senior Member
I've carried out some speed comparisons on alternate ways of returning a binary pattern depending on the returned ADC or similar value.
The tests were carried out on a 28X1 at 8MHz.

The returned value is modified to produce whole numbers to match the number of LEDS being driven (in this case 16 and 21 for the two different applications).

Three different bit patterns are required (see the LC and LA symbols in the first post).
The different methods used were;
1. Shift Left - achieved 1765 calculations/sec
2. Shift Left and REV - achieved 1370 calculations/sec
3. Shift left in a loop with the addition of 1 each time through the loop to produce a 'walking 0' bit (see LC above) - achieved 720 calculations /sec
4. Lookup the returned value in the declared symbols - achieved 250 calculations /sec
5. Repeated IF/ElseIf/EndIf construct - achieved 161 calculations /sec
6. Repeated IF/ElseIf/EndIf construct with fixed value so only the first value needs to be tested - achieved 476 calculations /sec
 
Last edited:

BCJKiwi

Senior Member
Have carried out a number of relative speed tests on different ways to turn a result from an ADC reading, into a bit pattern for 10 LEDs which will be controlled via an 8 bit, 2 bank I/O expander. The ADC reading, after manipulation is stored as 21 values from 0 thru 20
These are displayed on a 10 led bar graph with
**9 thru 0 building up the bar from right to left,
10 being all off
**20 thru 11 building up the bar from left to right.
i.e. all on at 0 decreasing to all off at the middle and increasing to all on in the opposite direction at 20.

The original program including the math for the ADC manipulation and method of display is in post #1 above.

The routines posted here give the timing results for alternate methods of creating the bit patterns required for the bar graph.
The issue as always is speed vs size - simple stored code that may be larger in program size but run faster,
compared to
more elegant/complex code which is smaller in size but may take longer to execute.
The logic options reviewed are
sequential If/ElseIf/Endif,
select case,
and
Branch techniques,
combined with
LOOKUP function to get stored bit patterns from symbol statements (symbols use no program memory space),
or
direct calulation of the bit pattens via shift ( << ) and REV functions.
Have also checked to see if there is any time penalty in using ptr & @ptr compared with direct use of variables. The ptr/@ptr is useful as it enables the stored variables to be retained without having to worry about re-use of bo/b1 etc (provided you keep a proper track of the ptr addresses of course!).
The first sections utilise setting up the bit patterns in symbol statements.
A1A and A1B use minimal Elseif and calculation then LOOKUP and check for the b2 variable vs @ptr option
A1C combines Branch and LOOKUP techniques
A2A and A2B use repeated ElseIf statements for each of the values and check for the b2 variable vs @ptr option.
A3A thru A3C use math incorporatiog shift and REV to calculate the bit pattern directly combined with;
A3A if/ElseIf/Endif
A3B Select Case
A3C Branch
Results for 1000 cycles of every value 21 within 2 nested for/next loops = 21,000 loops on a 28X1 revA.1 at 8Mhz internal clock
Note that nested loops add aproximately 50% to the time taken compared to hard coded values and no for/next loops (tested elsewhere).
........Code size.....Speed
A1A..132 bytes.....85 sec - Lookup - approx 2% penalty for ptr/@ptr
A1B..131 bytes.....83 sec - Lookup
A1C..153 bytes.....70 sec - Branch & Lookup
A2A..316 bytes.....123 sec - If/ElseIf/Endif and Lookup - approx 2% penalty for ptr/@ptr
A2B..312 bytes.....121 sec - If/ElseIf/Endif and Lookup
A3A..138 bytes.....80 sec - If/ElseIf/Endif and shift / REV
A3B..155 bytes.....90 sec - Select Case and Shift / REV
A3C..150 bytes.....73 sec - Branch and Shift / REV
With A3C, the Branch method, I also checked the timing for the position of the value along the array being tested, and the position of the label being referenced.
In this application, the most common values are at the centre of the range - i.e. either side of 10.
With the Branch statement and in Lookup, the testing has to be in order starting at 0 but the 'looked up' or 'Branch to' value/label can be in any order.
Thus the value 0 with the label for the action of 0 takes only 37 secs for 21000 cycles (no inner for/next loop).
With the value 10 and the label for 10 first, the time for 21000 cycles increased to 67 secs (no inner for/next loop).
With the value 20 and the label for 20 first (and the same code as for label Z0), the time for 21000 cycles increase to 87 secs (no inner for/next loop).
With the value 20 and the label for 20 last (and the same code as for label Z0), the time for 21000 cycles also 87 secs (no inner for/next loop).
Thus it can be seen there is a significant penalty for looking along the array (the same penalty occurs for LOOKUP) but no penalty for the position of the label.
So the larger number of variables involved the slower the lookup or Branch methods will be.

Code in following Post #7
 
Last edited:

BCJKiwi

Senior Member
Code for previous post #6

Code:
#picaxe 28x1
setfreq m8
#rem
symbol LA0 = %11111111
symbol LA1 = %11111110
symbol LA2 = %11111100
symbol LA3 = %11111000
symbol LA4 = %11110000
symbol LA5 = %11100000
symbol LA6 = %11000000
symbol LA7 = %10000000
symbol LA8 = %00000000
'
symbol LA10 = %11111111
symbol LA11 = %11111101
symbol LA12 = %11111100
symbol LA21 = %01111111
symbol LA22 = %00111111
symbol LA23 = %00011111
symbol LA24 = %00001111
symbol LA25 = %00000111
symbol LA26 = %00000011
symbol LA27 = %00000001
symbol LA28 = %00000000
#endrem
#rem
'A1A
ptr = 0      '132 bytes
for w6 = 0 to 1000
 for b3=0 to 20
' b5=9
 @ptr=b3
 If  @ptr = 10 then let b0 = LA0      'Led Number
  b1 = LA0         '10
 ElseIf @ptr > 10 and @ptr <13 then @ptr = @ptr-11
  lookup @ptr,(LA11,LA12),b1      '11 & 12
  let b0=LA10
 ElseIf @ptr > 1  and @ptr <10 then @ptr = @ptr-2
  lookup @ptr,(LA8,LA7,LA6,LA5,LA4,LA3,LA2,LA1),b0  '2 thru 9
  let b1=LA0
 ElseIf @ptr > 12 then @ptr = @ptr - 13
  lookup @ptr,(LA21,LA22,LA23,LA24,LA25,LA26,LA27,LA28),b0 '13 thru 20
  let b1=LA12
 else
  lookup @ptr,(LA2,LA1),b1      '0 & 1
  let b0=LA8
  endif
 next
next
sertxd ("END",cr,lf)    '85 secs for 1000 x 21 calcs = 247 calcs/sec
end
#endrem
#rem
'A1B     '131 bytes
for w6 = 0 to 1000
 for b3=0 to 20
  b2=b3
 If  b2 = 10 then let b0 = LA0      'Led Number
  b1 = LA0         '10
 ElseIf b2 > 10 and b2 <13 then b2 = b2-11
  lookup b2,(LA11,LA12),b1      '11 & 12
  let b0=LA10
 ElseIf b2 > 1  and b2 <10 then b2 = b2-2
  lookup b2,(LA8,LA7,LA6,LA5,LA4,LA3,LA2,LA1),b0   '2 thru 9
  let b1=LA0
 ElseIf b2 > 12 then b2 = b2 - 13
  lookup b2,(LA21,LA22,LA23,LA24,LA25,LA26,LA27,LA28),b0 '13 thru 20
  let b1=LA12
 else
  lookup b2,(LA2,LA1),b1       '0 & 1
  let b0=LA8
  endif
 next
next
sertxd ("END",cr,lf)    '83 secs for 1000 x 21 calcs = 253 calcs/sec
end
#endrem
 
#rem
'A1C      '153 bytes
for w6 = 0 to 1000
 for b3=0 to 20
 b2=b3
Branch b2,(Z0_1,Z0_1,Z2_9,Z2_9,Z2_9,Z2_9,Z2_9,Z2_9,Z2_9,Z2_9,Z10,Z11_12,Z11_12,Z13_20,Z13_20,Z13_20,Z13_20,Z13_20,Z13_20,Z13_20,Z13_20)
      Z10: b0 = LA0         '10
  b1 = LA0
  goto EndBranch
 Z11_12:
  b2 = b2-11
  lookup b2,(LA11,LA12),b1      '11 & 12
  b0=LA10
  goto EndBranch
 Z2_9:
  b2 = b2-2
  lookup b2,(LA8,LA7,LA6,LA5,LA4,LA3,LA2,LA1),b0   '2 thru 9
  let b1=LA0
  goto EndBranch
 Z13_20:
  b2 = b2 - 13
  lookup b2,(LA21,LA22,LA23,LA24,LA25,LA26,LA27,LA28),b0 '13 thru 20
  let b1=LA12
  goto EndBranch
 Z0_1:
  lookup b2,(LA2,LA1),b1       '0 & 1
  let b0=LA8
  goto EndBranch
EndBranch:  
 next
next
sertxd ("END",cr,lf)    '70 secs for 1000 x 21 calcs = 300 calcs/sec
end
#endrem
 
#rem
'A2A     '316 bytes
ptr = 10
for w6 = 0 to 1000
 for b3=0 to 20
' b3=10
 @ptr=b3
 If  @ptr = 10 then let b0 = LA0  : let b1=LA0 'no output for value 10 
 ElseIf @ptr = 9  then let b0 = LA1  : let b1=LA0 '9
 ElseIf @ptr = 8  then let b0 = LA2  : let b1=LA0 '8
 ElseIf @ptr = 11 then let b1 = LA11 : let b0=LA10 '11
 ElseIf @ptr = 12 then let b1 = LA12 : let b0=LA10 '12
 ElseIf @ptr = 7  then let b0 = LA3  : let b1=LA0 '7
 ElseIf @ptr = 13 then let b1 = LA12 : let b0=LA21 '13
 ElseIf @ptr = 6  then let b0 = LA4  : let b1=LA0 '6
 ElseIf @ptr = 14 then let b1 = LA12 : let b0=LA22 '14
 ElseIf @ptr = 5  then let b0 = LA5  : let b1=LA0 '5
 ElseIf @ptr = 15 then let b1 = LA12 : let b0=LA23 '15
 ElseIf @ptr = 4  then let b0 = LA6  : let b1=LA0 '4
 ElseIf @ptr = 16 then let b1 = LA12 : let b0=LA24 '16
 ElseIf @ptr = 3  then let b0 = LA7  : let b1=LA0 '3
 ElseIf @ptr = 17 then let b1 = LA12 : let b0=LA25 '17
 ElseIf @ptr = 2  then let b0 = LA8  : let b1=LA0 '2
 ElseIf @ptr = 18 then let b1 = LA12 : let b0=LA26 '18
 ElseIf @ptr = 1  then let b0 = LA8  : let b1=LA1 '1
 ElseIf @ptr = 19 then let b1 = LA12 : let b0=LA27 '19
 ElseIf @ptr = 0  then let b0 = LA8  : let b1=LA2 '0
 ElseIf @ptr = 20 then let b1 = LA12 : let b0=LA28 '20
 EndIf
 next
next
sertxd ("END",cr,lf)    '123 secs for 1000 x 21 calcs = 170 calcs /sec
end
#endrem
#rem
'A2B     '312 bytes
for w6 = 0 to 1000
 for b3=0 to 20
 b2 = b3
 If  b2 = 10 then let b0 = LA0  : let b1=LA0 'no output 0g == 125 
 ElseIf b2 = 9  then let b0 = LA1  : let b1=LA0 '9
 ElseIf b2 = 8  then let b0 = LA2  : let b1=LA0 '8
 ElseIf b2 = 11 then let b1 = LA11 : let b0=LA10 '11
 ElseIf b2 = 12 then let b1 = LA12 : let b0=LA10 '12
 ElseIf b2 = 7  then let b0 = LA3  : let b1=LA0 '7
 ElseIf b2 = 13 then let b1 = LA12 : let b0=LA21 '13
 ElseIf b2 = 6  then let b0 = LA4  : let b1=LA0 '6
 ElseIf b2 = 14 then let b1 = LA12 : let b0=LA22 '14
 ElseIf b2 = 5  then let b0 = LA5  : let b1=LA0 '5
 ElseIf b2 = 15 then let b1 = LA12 : let b0=LA23 '15
 ElseIf b2 = 4  then let b0 = LA6  : let b1=LA0 '4
 ElseIf b2 = 16 then let b1 = LA12 : let b0=LA24 '16
 ElseIf b2 = 3  then let b0 = LA7  : let b1=LA0 '3
 ElseIf b2 = 17 then let b1 = LA12 : let b0=LA25 '17
 ElseIf b2 = 2  then let b0 = LA8  : let b1=LA0 '2
 ElseIf b2 = 18 then let b1 = LA12 : let b0=LA26 '18
 ElseIf b2 = 1  then let b0 = LA8  : let b1=LA1 '1
 ElseIf b2 = 19 then let b1 = LA12 : let b0=LA27 '19
 ElseIf b2 = 0  then let b0 = LA8  : let b1=LA2 '0
 ElseIf b2 = 20 then let b1 = LA12 : let b0=LA28 '20
 EndIf
 next
next
sertxd ("END",cr,lf)    '121 secs for 1000 x 21 calcs = 173.5 calcs /sec
end
#endrem
#rem
'A3A     '138 bytes
for w6=0 to 1000
for b3 = 0 to 20 
 b2 = b3
 If     b2 = 10 then
        b0 = %11111111   '10
        b1 = %11111111
      ElseIf b2 = 0 then   '0
     b0 = 0
   b1 = %11111100
 ElseIf b2 = 1  then   '1
     b0 = 0
   b1 = %11111110
 ElseIf b2 < 10 then b2 = 10 - b2 '2 thru 9
   b0 = 255<<b2
   b1 = %11111111
 ElseIf b2 = 11 then   '11
     b0 = %11111111
   b1 = %11111101
 ElseIf b2 = 12 then   '12
     b0 = %11111111
   b1 = %11111100
 ElseIf b2 > 12 then b2 = b2 - 12 '12 thru 20
   b0 = 255<<b2 REV 8
    b1 = %11111100
  endif
next
next
sertxd ("END",cr,lf)    '80 secs for 1000 x 21 calcs = 262 /sec
end
#endrem
 
#rem
'A3B     '155 bytes
'order calculations so centre of renge are calculated first as these are most frequent
for w6=0 to 1000
for b3 = 0 to 20 
 b2 = b3
Select b2
 Case 10
        b0 = %11111111   '10
        b1 = %11111111
 Case 11     '11
     b0 = %11111111
   b1 = %11111101
 Case 12     '12
     b0 = %11111111
   b1 = %11111100
 Case 2 TO 9     '2 thru 9
   b2 = 10 - b2
   b0 = %11111111<<b2
   b1 = %11111111
 Case => 13
   b2 = b2 - 12   '13 thru 20
   b0 = %11111111<<b2 REV 8
    b1 = %11111100
 Case 1     '1
     b0 = %00000000
   b1 = %11111110
      Case 0     '0
     b0 = %00000000
   b1 = %11111100
Endselect
next
next
sertxd ("END",cr,lf)    '90 secs for 1000 x 21 calcs = 233 /sec 
end
#endrem
'#rem
'A3C     '150 bytes
'order calculations so centre of range are calculated first as these are most frequent
for w6=0 to 21000
for b3 = 0 to 20 
 b2 = b3
Branch b2,(Z0,Z1,Z2_9,Z2_9,Z2_9,Z2_9,Z2_9,Z2_9,Z2_9,Z2_9,Z10,Z11,Z12,Z13_20,Z13_20,Z13_20,Z13_20,Z13_20,Z13_20,Z13_20,Z13_20)
  Z0:        '0
    b0 = %00000000
   b1 = %11111100
     goto Branch_End
 Z1:        '1
    b0 = %00000000
   b1 = %11111110
     goto Branch_End
 Z2_9:      '2 thru 9
   b2 = 10 - b2
   b0 = %11111111<<b2
   b1 = %11111111
     goto Branch_End
  Z10:      '10
     b0 = %11111111
     b1 = %11111111
     goto Branch_End
 Z11:      '11
    b0 = %11111111
   b1 = %11111101
     goto Branch_End
 Z12:      '12
    b0 = %11111111
   b1 = %11111100
     goto Branch_End
 Z13_20:     '13 thru 20
    b2 = b2 - 12
   b0 = %11111111<<b2 REV 8
    b1 = %11111100
     goto Branch_End
Branch_End:
next
next
sertxd ("END",cr,lf) '73  secs for 1000 x 21 calcs = 287 /sec & labels as shown
    '37  secs if b2 always = 0  & labels as shown (Z0: first)
    '62  secs if b2 always = 10 & label Z10: first
    '87  secs if b2 always = 20 & labels as shown (Z20: last) but with same code as Z0 
end
'#endrem
 
Last edited:

BCJKiwi

Senior Member
However the winner is!
(have saved the best to last- courtesy of Hippy!)

This code is much smaller than that shown above, and is the fastest.
It uses the eeprom command to store the bit pattern data that was previously stored via the symbol commands but in a slightly different manner.
The program code accesses this stored data directly from memory via the read command.

Code is just 51 bytes (data is stored separately from program space on the 28X1) and takes 53 secs for 21,000 cycles onthe 28X1 RevA.1 at 8MHz.

Code:
#rem
'WINNER       '51 bytes
'               b0,       b1
eeprom 214,(%00000000,%11111100)  '0
eeprom 216,(%00000000,%11111110)  '1
eeprom 218,(%00000000,%11111111)  '2
eeprom 220,(%10000000,%11111111)  '3
eeprom 222,(%11000000,%11111111)  '4
eeprom 224,(%11100000,%11111111)  '5
eeprom 226,(%11110000,%11111111)  '6
eeprom 228,(%11111000,%11111111)  '7
eeprom 230,(%11111100,%11111111)  '8
eeprom 232,(%11111110,%11111111)  '9
eeprom 234,(%11111111,%11111111)  '10
eeprom 236,(%11111111,%11111101)  '11
eeprom 238,(%11111111,%11111100)  '12
eeprom 240,(%01111111,%11111100)  '13
eeprom 242,(%00111111,%11111100)  '14
eeprom 244,(%00011111,%11111100)  '15
eeprom 246,(%00001111,%11111100)  '16
eeprom 248,(%00000111,%11111100)  '17
eeprom 250,(%00000011,%11111100)  '18
eeprom 252,(%00000001,%11111100)  '19
eeprom 254,(%00000000,%11111100)  '20

 
for w6 = 0 to 1000
 for b3=0 to 20
 b2=b3
 b2=b2*2+214
 read b2,b0,b1
 next
next
sertxd ("END",cr,lf)    '53 secs for 1000 x 21 calcs = 396 calcs/sec
end
#endrem
 
Last edited:
Top