Help please, with Rotary Encoder (code) from 08m to 40X2...

OLDmarty

Senior Member
Hi All,

This is my FIRST trial using interrupts, something i've never used before, so it's baby steps for me at the moment ;-)

I'm trying to migrate some Rotary Encoder code from an 08m to my 40X2.
It's originally from this posting by "Vertigo" Here

I have prefixed all MY changes with ";;OLDMARTY" and the original (08m) code is prefixed with ";;ORIGINAL" just so you can see what i've changed.

I'm using Port A on the 40X2 (bits A.0, A.1), so everyting is migrated from Port C on the 08m to Port A.
(I've confirmed in the SETINT docs, that 40X2 can use interrupts on A.0 to A.3)

At the moment my 40X2 code seems to only count in one direction, always decreasing the counts with each 'click' of the encoder.
I'm using a standard 2 bit quadrature encoder, with pins A and B being the outputs and a common pin.
Am i doing something as simple as using pins A & B the wrong way around?

23195

It looks like simple code (for me) to understand, but have i missed something in the migration???


Code:
;
;OLDMARTY ROTARY ENCODER TRIAL for 40X2
;
;
#PICAXE 40X2            ; Define PICAXE 40X2 type
#NO_DATA                ;Stop EEPROM data from being cleared during programming
#NO_TABLE                ;Ignore TABLE data - loads program faster
#Terminal 9600
;
;
'picaxe 08M
'
'           +V 1 U 8 0V
'    GND - 10K 2   7 (0) OUT
' I/O/ADC4 (4) 3   6 (1) I/O/ADC1 --- rotary encoder
'   IN3    (3) 4   5 (2) I/O/ADC2 --- rotary encoder
'
' b1  b0 b3  b2 b5  b4 b7  b6 b9  b8 b11 b10 b13 b12
' --w0-- --w1-- --w2-- --w3-- --w4-- --w5--- --w6---

'b0 = bit7  : bit6  : bit5  : bit4  : bit3  : bit2  : bit1 : bit0
'b1 = bit15 : bit14 : bit13 : bit12 : bit11 : bit10 : bit9 : bit8

#rem

Rotary encoder connection:

   0V
   |
  4.7K
   |
o--.----(A) pin1 (phys 6) - ;; OLDMARTY Port A.0
o--330-- +5V
o--.----(B) pin2 (phys 5) - ;; OLDMARTY Port A.1
   |
  4.7K
   |
   0V

Encoder result (early detection):
pin1 pin2
  1    0  one direction
  0    1  other direction
  0    0  init and final (= "detent") status

One direction: pin1 goes high before pin2
         ___     ___
pin1 ___|   |___|   |___
           ___     ___
pin2 _____|   |___|   |___

Other direction: pin2 goes high before pin1
           ___     ___
pin1 _____|   |___|   |___
         ___     ___
pin2 ___|   |___|   |___

#endrem

'           Used bits                                          xxxx   xxxx
symbol getBits   = b0 'b0 = bit7 : bit6 : bit5 : bit4 : bit3 : bit2 : bit1 : bit0
symbol dir       = b1
symbol counter   = b3

;;ORIGINAL
;;setint %00000010,%00000010 'interrupt on pin1 (C.1) high only

;;OLDMARTY
setint %00000001,%00000001,A ;interrupt on pin A.0 high only

main:
  do
   sertxd("Main loop - Counter=",#b3,13,10)
   pause 250
  loop
  
  
interrupt:

;;ORIGINAL
 ;;bit2 = pin2: bit1 = pin1       'save rotary encoder pins status

 ;;OLDMARTY
 bit2 = pinA.1: bit1 = pinA.0       'save rotary encoder pins status

 ;;ORIGINAL
 ;;getBits = getBits & %00000110 'isolate rotary encoder pins

  ;;OLDMARTY
 getBits = getBits & %00000011 'isolate rotary encoder pins ;; on pins 0 & 1 (MARTY A.1, A.0)

 if getBits <> 0 then           'if both pins are low, the direction is undetermined: discard
  dir = bit2 * 2                'direction: if bit2=low then dir=0; if bit2=high then dir=2
  counter = counter - 1 + dir   'change counter variable accordingly
  do while getBits <> 0         'wait for the encoder to go to the next "detent" position

 ;;ORIGINAL
 ;;getBits = pins & %000000110    ;"pins" on an 08M refers to the entire byte of C port. 'pins' is replaced with 'pinsC' on X2 devices etc.

 ;;OLDMARTY
 getBits = pinsA & %000000011

  loop
 endif

;;ORIGINAL
;;setint %00000010,%00000010     'restore interrupt on pin1 high

;;OLDMARTY
 setint %00000001,%00000001,A ;interrupt on pin A.0 high only

 return
 

hippy

Technical Support
Staff member
bit2 = pinA.1: bit1 = pinA.0
getBits = getBits & %00000011

That's where the mismatch is. 'getBits' is 'b0'. You are setting 'bit2' and 'bit1' but then anding 'bit1' and 'bit0', losing 'bit2'.
 

OLDmarty

Senior Member
bit2 = pinA.1: bit1 = pinA.0
getBits = getBits & %00000011

That's where the mismatch is. 'getBits' is 'b0'. You are setting 'bit2' and 'bit1' but then anding 'bit1' and 'bit0', losing 'bit2'.
Oh silly me.....so i should have initially changed the line:
bit2 = pinA.1: bit1 = pinA.0
to
bit1 = pinA.1: bit0 = pinA.0

Damn my eyes, but i was fairly close lol ;-)
 

hippy

Technical Support
Staff member
That, corrected ...

bit1 = pinA.1: bit0 = pinA.0
getBits = getBits & %00000011

Can be reduced to a simpler "getBits = pinsA & %00000011".

I also now think that "dir = bit2 * 2" is wrong, should be "dir = bit1 * 2", or a more simple "dir = getBit & %00000010".

Your complete code can be simplified to -
Code:
#Picaxe 40X2

symbol getBits = b0
symbol counter = w1

Gosub Interrupt_Enable
Do
  Pause 100
Loop

Interrupt:
  getBits = pinsA & %00000011
  If getBits <> 0 Then
    counter = getBits & %00000010 + counter - 1
    Do
      getBits = pinsA & %00000011
    Loop Until getBits = %00000000
  End If

Interrupt_Enable:
  SetInt %00000001, %00000001, A
  Return
 

OLDmarty

Senior Member
That, corrected ...

bit1 = pinA.1: bit0 = pinA.0
getBits = getBits & %00000011

Can be reduced to a simpler "getBits = pinsA & %00000011".

I also now think that "dir = bit2 * 2" is wrong, should be "dir = bit1 * 2", or a more simple "dir = getBit & %00000010".
Thanks Hippy,
I'll try the code update(s) tomorrow and confirm that it's all ok (or not).

Thanks again.
 

OLDmarty

Senior Member
That, corrected ...

bit1 = pinA.1: bit0 = pinA.0
getBits = getBits & %00000011

Can be reduced to a simpler "getBits = pinsA & %00000011".

I also now think that "dir = bit2 * 2" is wrong, should be "dir = bit1 * 2", or a more simple "dir = getBit & %00000010".

Your complete code can be simplified to -
Code:
#Picaxe 40X2

symbol getBits = b0
symbol counter = w1

Gosub Interrupt_Enable
Do
  Pause 100
Loop

Interrupt:
  getBits = pinsA & %00000011
  If getBits <> 0 Then
    counter = getBits & %00000010 + counter - 1
    Do
      getBits = pinsA & %00000011
    Loop Until getBits = %00000000
  End If

Interrupt_Enable:
  SetInt %00000001, %00000001, A
  Return

Hi Hippy,

I've adjusted your reduced code a little, and working fine....
I changed the counter to B1, as i (barely) need an 8bit counter, and i added the terminal so i can see what it's doing.

Quick question, how can i set a maximum value for the counter? I only need it to have 16 values (0 to 15).
Is there a max value i need to use?

I'm toying between 2 options of the maximum value:
1) When the counter reaches 15, it won't go any higher in value, but will obviously decrease back towards '0' by rotating the opposite way.
or,
2) When the counter reaches 15, the NEXT click will go back to '0', and continue a 0 to 15 count as the rotation continues upward clicking.
(or when the counter reaches 0, the NEXT click will go back to '15', and continue a 15 to 0 count as the rotation continues downward clicking).

I did manage to add a 'max' command to the following line:
Code:
counter = getBits & %00000010 + counter - 1 max 15
....and this stops from advancing beyond the value 15, but it will still go below 0 (255 downwards).
I tried adding a min 0 into that line, but it does nothing, clearly i'm not adjusting the correct line of code for the minimum limit.


Code:
#PICAXE 40X2            ; Define PICAXE 40X2 type
#NO_DATA                ;Stop EEPROM data from being cleared during programming
#NO_TABLE                ;Ignore TABLE data - loads program faster
#Terminal 9600

symbol getBits = b0
symbol counter = b1

Gosub Interrupt_Enable
  do
   sertxd("Counter= ",#counter,13,10)
   pause 200
  loop

Interrupt:
  getBits = pinsA & %00000011
  If getBits <> 0 Then
    counter = getBits & %00000010 + counter - 1
    Do
      getBits = pinsA & %00000011
    Loop Until getBits = %00000000
  End If

Interrupt_Enable:
  SetInt %00000001, %00000001, A
  Return
 
Last edited:

hippy

Technical Support
Staff member
To limit the counter to 0 to 15, you could use an IF based on the 'bit1' value but the best one-liner would be -

counter = counter + bit1 Min 1 + bit1 - 1 Max 15

Test code for Simulation to prove that works as desired -

Code:
#Picaxe 40X2

Symbol getBits = b0
Symbol counter = b1
Symbol initial = b3

For initial = 0 To 15
  counter = initial
  bit1    = 0 ; -1
  counter = counter + bit1 Min 1 + bit1 - 1 Max 15
  SerTxd( #initial, " - 1 = ", #counter, CR, LF )
Next
For initial = 0 To 15
  counter = initial
  bit1    = 1 ; +1
  counter = counter + bit1 Min 1 + bit1 - 1 Max 15
  SerTxd( #initial, " + 1 = ", #counter, CR, LF )
Next
To wrap round, 15+1 to 0, 0-1 to 15 -

counter = getBits & %00000010 + counter - 1 & 15
 
Last edited:

OLDmarty

Senior Member
To limit the counter to 0 to 15, you could use an IF based on the 'bit1' value but the best one-liner would be -

counter = counter + bit1 Min 1 + bit1 - 1 Max 15

Test code for Simulation to prove that works as desired -

Code:
#Picaxe 40X2

Symbol getBits = b0
Symbol counter = b1
Symbol initial = b3

For initial = 0 To 15
  counter = initial
  bit1    = 0 ; -1
  counter = counter + bit1 Min 1 + bit1 - 1 Max 15
  SerTxd( #initial, " - 1 = ", #counter, CR, LF )
Next
For initial = 0 To 15
  counter = initial
  bit1    = 1 ; +1
  counter = counter + bit1 Min 1 + bit1 - 1 Max 15
  SerTxd( #initial, " + 1 = ", #counter, CR, LF )
Next
To wrap round, 15+1 to 0, 0-1 to 15 -

counter = getBits & %00000010 + counter - 1 & 15

Hi Hippy, so do you mean that i replace my 'counter' line of code with this new one? (counter = counter + bit1 Min 1 + bit1 - 1 Max 15 )

I'll tinker with these updates tomorrow and see where it leads to ;-)

Thanks again.
 

hippy

Technical Support
Staff member
Yes, replace the earlier -

counter = getBits & %00000010 + counter - 1

with

counter = counter + bit1 Min 1 + bit1 - 1 Max 15
 

OLDmarty

Senior Member
Yes, replace the earlier -
counter = getBits & %00000010 + counter - 1
with
counter = counter + bit1 Min 1 + bit1 - 1 Max 15
Thanks again Hippy, works a treat ;-)

OK, on a sidenote, can i easily add 1 (or more) rotary encoders by using multiple SETINT's, each with different bits to arm for triggering from each encoder?

I've scratched out a modification of your code, but added counter2 and getbits2 variables and modified a 2nd SETINT interrupt routine to read a 2nd encoder attached to A.2 and A.3 etc.
I realise the code word "interrupt:" is reserved, so i wrote an "interrupt2:" section just to highlilght what i'm trying to work out.


I think i'm on the right track, but maybe the wrong train ;-)

Code:
#PICAXE 40X2            ; Define PICAXE 40X2 type
#NO_DATA                ;Stop EEPROM data from being cleared during programming
#NO_TABLE                ;Ignore TABLE data - loads program faster
#Terminal 9600

symbol getBits = b0
symbol getBits2 = b1
symbol counter = b2
symbol counter2 = b3

Gosub Interrupt_Enable
Gosub Interrupt_Enable2    ;????
  do
   sertxd("Counter= ",#counter,"Counter2= ",#counter2,13,10)
   pause 200
  loop

Interrupt:
  getBits = pinsA & %00000011
  If getBits <> 0 Then
    counter = counter + bit1 Min 1 + bit1 - 1 Max 15    ; Counts 0 to 15 and STOPS at 15, (and 15 to 0 and STOPS at 0).

    Do
      getBits = pinsA & %00000011
    Loop Until getBits = %00000000
  End If


;#############################################
Interrupt2: ; ??????
  getBits2 = pinsA & %00001100
  If getBits2 <> 0 Then
    counter2 = counter2 + bit3 Min 1 + bit3 - 1 Max 15    ; Counts 0 to 15 and STOPS at 15, (and 15 to 0 and STOPS at 0).

    Do
      getBits2 = pinsA & %00001100
    Loop Until getBits2 = %00000000
  End If
;#############################################



Interrupt_Enable:
  SetInt %00000001, %00000001, A    ;Interrupt on Encoder #1 on pin A.0 (active high)
  Return
 
  Interrupt_Enable2:
  SetInt %00000100, %00000100, A    ;Interrupt on Encoder #2 on pin A.2 (active high)
  Return
 

hippy

Technical Support
Staff member
OK, on a sidenote, can i easily add 1 (or more) rotary encoders by using multiple SETINT's, each with different bits to arm for triggering from each encoder?
Not necessarily "easily", but it can be done.

If, as seems to be the case here, your encoders give a short pulse when moved rather than being pure quadrature encoders, using a SETINT on either A, determining which it is, and waiting for the relevant pins to have returned to zero before continuing may work.

Otherwise more complicated interrupt mechanisms need to be used to avoid one encoder from blocking the other.

There's some code here which shows how to interrupt on two or more sources, and it should be easy enough to modify that to increment your counters within that -

https://picaxeforum.co.uk/threads/function-setint.31574/#post-327536

Code:
#Picaxe 20M2
#Terminal 4800

;               76543210
Symbol MASKA = %00000010 ; C.1
Symbol MASKB = %00000100 ; C.2

Symbol MASK  = %00000110 ; All of the above

Symbol level = b2

PowerOnReset:
  SerTxd( "Started", CR, LF )
  Gosub Interrupt_Enable

MainLoop:
  Do
    Pause 100
  Loop

Interrupt:

  b0 = pinsC ^ level

  b1 = b0 And MASKA
  If b1 <> 0 Then
    b1 = b1 And level
    If b1 <> 0 Then
      SerTxd( "A (C.1) went low", CR, LF )
    Else
      SerTxd( "A (C.1) went high", CR, LF )
    End If
  End If

  b1 = b0 And MASKB
  If b1 <> 0 Then
    b1 = b1 & level
    If b1 <> 0 Then
      SerTxd( "B (C.2) went low", CR, LF )
    Else
      SerTxd( "B (C.2) went high", CR, LF )
    End If
  End If
  
  level = level ^ b0 And MASK
  SetInt Not level, MASK
  Return

Interrupt_Enable:
  level = pinsC And MASK
  SetInt Not level, MASK
  Return
Which pins are you using for your two encoders ?
 

OLDmarty

Senior Member
Which pins are you using for your two encoders ?
Thanks Hippy, i'll try out your code and readup the other info you linked to.
Yes, i imagine it does get a bit hairy, trying to process multiple interrupts and not have them lockout each other (or other devices) from being processed in a timely manner.

Currently my 1st encoder is on Port A.0 & A.1, and the intended 2nd encoder will be on Port A.2 & A.3
 

hippy

Technical Support
Staff member
Here's a optimised / simplified version of what I think you will need -

Code:
#Picaxe 40X2
#Terminal 9600

;               76543210
Symbol MASKA = %00000001 ; A.0
Symbol MASKB = %00000100 ; A.2

Symbol MASK  = %00000101 ; All of the above

Symbol reserveB0 = b0

Symbol countA    = b2
Symbol countB    = b3
Symbol lastA     = b4
Symbol lastB     = b5

PowerOnReset:
  SerTxd( "Started", CR, LF )
  Gosub Interrupt_Enable

MainLoop:
  Do
    If countA <> lastA Then
      SerTxd( "A = ", #countA, CR, LF )
      lastA = countA
    End If
    If countB <> lastB Then
      SerTxd( "B = ", #countB, CR, LF )
      lastB = countB
    End If
  Loop

Interrupt:

  b0 = pinsA

  If bit0 <> 0 Then
    countA = CountA + bit1 Min 1 + bit1 - 1 Max 15
  End If

  If bit2 <> 0 Then
    countB = CountB + bit3 Min 1 + bit3 - 1 Max 15
  End If
  
  b0 = b0 And MASK
  SetInt Not b0, MASK, A
  Return

Interrupt_Enable:
  b0 = pinsA And MASK
  SetInt Not b0, MASK, A
  Return
 

OLDmarty

Senior Member
Hi Hippy, the revised code works correctly as i needed.

Ok, i just re-hacked my test jig to use 2x rotary encoders...
I'm now sending CountA and CountB variables to 2 different LED displays quite efficiently.

Thanks again.
 

OLDmarty

Senior Member
Hi Hippy,

In your most recent code, i tried migrating it from PortA onto PortD.

I believe i've adjusted all the correct bits and maths, but i cannot get the code to run.
The terminal opens and simply shows the "Started" text, but i don't have any readings from CountA or B anymore.

Today, i simply moved my 2 rotary encoders from a small proto-board, and mounted into an existing test-jig box.
This box has 4 pots/wires, wired to PortD on D.0 to D.3, so i've set aside D4 & D.5 for Rotary 'A' and D.6 & D.7 for Rotary 'B'.

I've re-checked the wiring to the encoders, there is voltage on the Rotary commons and the pulldown resistors wired to GND.
The A/B terminals have been checked and connected on D.4 to D.7 as i planned.

I've double-remm'ed [ ;; ] your original Port.A related lines, and added my own Port.D codes.
Surely i've overlooked something in the equations?

Code:
#PICAXE 40X2            ; Define PICAXE 40X2 type
#NO_DATA                ;Stop EEPROM data from being cleared during programming
#NO_TABLE                ;Ignore TABLE data - loads program faster
#Terminal 9600


;                                  76543210
;;Symbol MASKA = %00000001 ; A.0
;;Symbol MASKB = %00000100 ; A.2
;;Symbol MASK  = %00000101 ; All of the above

;                                 76543210
Symbol MASKA = %00010000 ; D.4
Symbol MASKB = %01000000 ; D.6
Symbol MASK  = %01010000 ; All of the above

Symbol reserveB0 = b0

Symbol countA    = b2
Symbol countB    = b3
Symbol lastA     = b4
Symbol lastB     = b5


PowerOnReset:
  SerTxd( "Started", CR, LF )
  Gosub Interrupt_Enable

MainLoop:
  Do
    If countA <> lastA Then
      SerTxd( "A = ", #countA, CR, LF )
      lastA = countA
    End If
    If countB <> lastB Then
      SerTxd( "B = ", #countB, CR, LF )
      lastB = countB
    End If

  Loop



Interrupt:

  ;;b0 = pinsA
  b0 = pinsD
  ;;If bit0 <> 0 Then
  If bit4 <> 0 Then
    ;;countA = CountA + bit1 Min 1 + bit1 - 1 Max 15
        countA = CountA + bit5 Min 1 + bit5 - 1 Max 15
  End If

  ;;If bit2 <> 0 Then
  If bit6 <> 0 Then
    ;;countB = CountB + bit3 Min 1 + bit3 - 1 Max 15
        countB = CountB + bit7 Min 1 + bit7 - 1 Max 15
  End If

  b0 = b0 And MASK
  SetInt Not b0, MASK, A
  Return

Interrupt_Enable:
  ;;b0 = pinsA And MASK
    b0 = pinsD And MASK
  SetInt Not b0, MASK, A
  Return
 

hippy

Technical Support
Staff member
Code:
  SetInt Not b0, MASK, A
  SetInt Not b0, MASK, A
Those should be ", D"
 

AllyCat

Senior Member
Hi,

I suspect the (first) problem is:
SetInt Not b0, MASK, A
where the Command Reference says:

SETINT NOT input,mask,port(port selection on X2 only)
Input - is a variable/constant (0-255) which specifies input condition.
Mask - is variable/constant (0-255) which specifies the mask.
Port - is the X2 port (A,B,C,D).

Ah, beaten by hippy again. ;)

Cheers, Alan
 

OLDmarty

Senior Member
Hahahaha, damn, i was close, i looked at that code for an hour thinking "what's wrong with it?"

I clearly overlooked the "Mask, A", because i was looking at it as being the symbol MASKA and MASKB etc.

Thanks again guys, I'll go retry the code when i'm back at my workbench tomorrow....

Damn eyes, sheesh ;-)
 

hippy

Technical Support
Staff member
This is a classic example of why it is often best to define all the items used in the program at the top of the code so only those need to change when different pins are chosen or the code is ported to a different PICAXE chip.

Otherwise having 'magic numbers' and hard-coded values in the code makes it common to miss something as happened here, and it's often hard to spot what has been missed when it's complicated code.

So, what the code should have been, configured for the latest wiring used -
Code:
#Picaxe 40X2
#Terminal 9600

#Define PORT       D         ; D.x

;                   76543210
Symbol MASKA     = %00010000 ; D.4
Symbol MASKB     = %01000000 ; D.6

Symbol MASK      = %01010000 ; All the above

Symbol pinsX     = pinsD     ; D.x

Symbol clkA      = bit4      ; D.4
Symbol dirA      = bit5      ; D.5
Symbol clkB      = bit6      ; D.6
Symbol dirB      = bit7      ; D.7

Symbol reserveB0 = b0

Symbol countA    = b2
Symbol countB    = b3
Symbol lastA     = b4
Symbol lastB     = b5

PowerOnReset:
  SerTxd( "Started", CR, LF )
  Gosub Interrupt_Enable

MainLoop:
  Do
    If countA <> lastA Then
      SerTxd( "A = ", #countA, CR, LF )
      lastA = countA
    End If
    If countB <> lastB Then
      SerTxd( "B = ", #countB, CR, LF )
      lastB = countB
    End If
  Loop

Interrupt:

  b0 = pinsX

  If clkA <> 0 Then
    countA = CountA + dirA Min 1 + dirA - 1 Max 15
  End If

  If clkB <> 0 Then
    countB = CountB + dirB Min 1 + dirB - 1 Max 15
  End If
  
  b0 = b0 And MASK
  SetInt Not b0, MASK, PORT
  Return

Interrupt_Enable:
  b0 = pinsX And MASK
  SetInt Not b0, MASK, PORT
  Return
The 'PORT' definition has to be a #DEFINE because the "D" is not a variable or number which can be used within SYMBOL.

And note there is no "=" used with #DEFINE, or that becomes part of what is substituted wherever 'PORT' appears; which will usually cause a syntax error.
 

OLDmarty

Senior Member
This is a classic example of why it is often best to define all the items used in the program at the top of the code so only those need to change when different pins are chosen or the code is ported to a different PICAXE chip.

Otherwise having 'magic numbers' and hard-coded values in the code makes it common to miss something as happened here, and it's often hard to spot what has been missed when it's complicated code.

So, what the code should have been, configured for the latest wiring used -
Code:
#Picaxe 40X2
#Terminal 9600

#Define PORT       D         ; D.x

;                   76543210
Symbol MASKA     = %00010000 ; D.4
Symbol MASKB     = %01000000 ; D.6

Symbol MASK      = %01010000 ; All the above

Symbol pinsX     = pinsD     ; D.x

Symbol clkA      = bit4      ; D.4
Symbol dirA      = bit5      ; D.5
Symbol clkB      = bit6      ; D.6
Symbol dirB      = bit7      ; D.7

Symbol reserveB0 = b0

Symbol countA    = b2
Symbol countB    = b3
Symbol lastA     = b4
Symbol lastB     = b5

PowerOnReset:
  SerTxd( "Started", CR, LF )
  Gosub Interrupt_Enable

MainLoop:
  Do
    If countA <> lastA Then
      SerTxd( "A = ", #countA, CR, LF )
      lastA = countA
    End If
    If countB <> lastB Then
      SerTxd( "B = ", #countB, CR, LF )
      lastB = countB
    End If
  Loop

Interrupt:

  b0 = pinsX

  If clkA <> 0 Then
    countA = CountA + dirA Min 1 + dirA - 1 Max 15
  End If

  If clkB <> 0 Then
    countB = CountB + dirB Min 1 + dirB - 1 Max 15
  End If

  b0 = b0 And MASK
  SetInt Not b0, MASK, PORT
  Return

Interrupt_Enable:
  b0 = pinsX And MASK
  SetInt Not b0, MASK, PORT
  Return
The 'PORT' definition has to be a #DEFINE because the "D" is not a variable or number which can be used within SYMBOL.

And note there is no "=" used with #DEFINE, or that becomes part of what is substituted wherever 'PORT' appears; which will usually cause a syntax error.
Thanks Hippy,

Firstly, the "Mask, D" change in my previous code today works perfectly now ;-)
I will apply your definition rules to my code to make it easier to understand and edit in future.

Secondly, I will encourage myself to stick to a standard structure of my definitions in my future coding....always learning ;-)
 

OLDmarty

Senior Member
This is a classic example of why it is often best to define all the items used in the program at the top of the code so only those need to change when different pins are chosen or the code is ported to a different PICAXE chip.

Otherwise having 'magic numbers' and hard-coded values in the code makes it common to miss something as happened here, and it's often hard to spot what has been missed when it's complicated code.

So, what the code should have been, configured for the latest wiring used -
Code:
#Picaxe 40X2
#Terminal 9600

#Define PORT       D         ; D.x

;                   76543210
Symbol MASKA     = %00010000 ; D.4
Symbol MASKB     = %01000000 ; D.6

Symbol MASK      = %01010000 ; All the above

Symbol pinsX     = pinsD     ; D.x

Symbol clkA      = bit4      ; D.4
Symbol dirA      = bit5      ; D.5
Symbol clkB      = bit6      ; D.6
Symbol dirB      = bit7      ; D.7

Symbol reserveB0 = b0

Symbol countA    = b2
Symbol countB    = b3
Symbol lastA     = b4
Symbol lastB     = b5

PowerOnReset:
  SerTxd( "Started", CR, LF )
  Gosub Interrupt_Enable

MainLoop:
  Do
    If countA <> lastA Then
      SerTxd( "A = ", #countA, CR, LF )
      lastA = countA
    End If
    If countB <> lastB Then
      SerTxd( "B = ", #countB, CR, LF )
      lastB = countB
    End If
  Loop

Interrupt:

  b0 = pinsX

  If clkA <> 0 Then
    countA = CountA + dirA Min 1 + dirA - 1 Max 15
  End If

  If clkB <> 0 Then
    countB = CountB + dirB Min 1 + dirB - 1 Max 15
  End If
 
  b0 = b0 And MASK
  SetInt Not b0, MASK, PORT
  Return

Interrupt_Enable:
  b0 = pinsX And MASK
  SetInt Not b0, MASK, PORT
  Return
The 'PORT' definition has to be a #DEFINE because the "D" is not a variable or number which can be used within SYMBOL.

And note there is no "=" used with #DEFINE, or that becomes part of what is substituted wherever 'PORT' appears; which will usually cause a syntax error.

Hi Hippy,

Back in post #8, you showed how to use the line "counter = getBits & %00000010 + counter - 1 & 15" to allow the encoder to cycle and repeat itself 0 to 15 repeatedly instead of stopping at 0 or 15 as the end-stops..

Now your code has changed significantly, so can you highlight how i can edit the new line of code (to repeat 0 to 15 over and over) again?

I imagine we just need to tinker with this section again, but i'm getting lost in the maths with the variable changes recently added:

Code:
 b0 = pinsX

  If clkA <> 0 Then
    countA = CountA + dirA Min 1 + dirA - 1 Max 15     ;Allow counting 0 to 15, or 15 to 0 and STOP at 15 or 0.
  End If

  If clkB <> 0 Then
    countB = CountB + dirB Min 1 + dirB - 1 Max 15    ;Allow counting 0 to 15, or 15 to 0 and STOP at 15 or 0.
  End If

Thanks in advance.
 

hippy

Technical Support
Staff member
This will limit to never going below zero and never above 15 ...

countA = CountA + dirA Min 1 + dirA - 1 Max 15

This will roll-over, so 0 - 1 = 15, 15 + 1 = 0 ...

countA = countA + dirA + dirA - 1 & 15

The best way to implement that in an easy to modify program would be to add two macros and then update the count lines appropriately -
Code:
#Macro CountZeroToLimit( countX, dirX, maxX )
  countX = countX + dirX Min 1 + dirX - 1 Max maxX
#Endmacro

#Macro CountWithRollOver( countX, dirX, maxX )
  countX = countX + dirX + dirX - 1 & maxX
#Endmacro
Code:
Symbol MAXA = 15 ; Limit countA to 0..15
Symbol MAXB = 15 ; Limit countB to 0..15

If clkA <> 0 Then
  CountZeroToLimit( countA, dirA, MAXA )
End If

If clkB <> 0 Then
  CountWithRollover( countB, dirB, MAXB )
End If
 

OLDmarty

Senior Member
This will limit to never going below zero and never above 15 ...

countA = CountA + dirA Min 1 + dirA - 1 Max 15

This will roll-over, so 0 - 1 = 15, 15 + 1 = 0 ...

countA = countA + dirA + dirA - 1 & 15

The best way to implement that in an easy to modify program would be to add two macros and then update the count lines appropriately -
Code:
#Macro CountZeroToLimit( countX, dirX, maxX )
  countX = countX + dirX Min 1 + dirX - 1 Max maxX
#Endmacro

#Macro CountWithRollOver( countX, dirX, maxX )
  countX = countX + dirX + dirX - 1 & maxX
#Endmacro
Code:
Symbol MAXA = 15 ; Limit countA to 0..15
Symbol MAXB = 15 ; Limit countB to 0..15

If clkA <> 0 Then
  CountZeroToLimit( countA, dirA, MAXA )
End If

If clkB <> 0 Then
  CountWithRollover( countB, dirB, MAXB )
End If
Thanks Hippy for clearing that up.

I'll add the 2 methods onto each of my 2 encoders, 1 will be 0-15 limited, and the other will be 0-15 repeating (until i determine which of the methods works best for my project).

Thanks again.
 

AllyCat

Senior Member
Hi,
I clearly overlooked the "Mask, A", because i was looking at it as being the symbol MASKA and MASKB etc.
Yes, to be fair, it is rather an "inconsistent" syntax. Witness that it needs a #DEFINE rather than a SYMBOL command. Is it what's called a "switch" in computer jargon, (e.g. /D) ? Normally in PICaxe Basic one would expect a "number" (or variable), e.g. 0, 1, 2 or 3 (or perhaps 0, 8 , 16, 24) which would/could have a predefined symbol declaration such as "INTPORT_D".

But IIRC an even stranger example is PWMDIV16 (etc.) in the PWMOUT command, which also isn't a "number" (so can make coding quite clumsy).

Cheers, Alan.
 

hippy

Technical Support
Staff member
Is it what's called a "switch" in computer jargon, (e.g. /D) ?
Very similar, so that's a good way of thinking of it. Most PICAXE commands are represented by a command token then the argument tokens so a "Count C.1, 1000, w0" command would appear in the object code something like -
Code:
CMD    COUNT
PIN    C.1
NUM    1000
VAR    w0
For commands like SETINT and PWMOUT the port and division are effectively a part of the command token itself, appear like -
Code:
CMD    SETINT.D      CMD    PWMOUT/4
VAR    b0            PIN    C.5
NUM    MASK          VAR    period
                     VAR    duty
The port and division arguments cannot be passed over as parameters for the firmware to determine at runtime, but need to be determined by the compiler during compilation. Hence why only pre-defined name modifiers can be used, rather than variables.

It's actually a little different to the above in reality, but that in essence is what's going on.

Those modifiers could have been passed as command parameters but that means an extra parameter for those commands every time they are used which makes programs longer, and the firmware has to untangle what those parameters mean which adds to the firmware code. There are other technical issues which make this more appropriate as well, so non-modifiable parameters exist in a few case.

Most times this isn't a problem; SETINT port and PWMOUT division don't dynamically change within a program, but where they do an IF-ELSE or SELECT-CASE and the appropriate command to execute will solve that.
 

OLDmarty

Senior Member
This will limit to never going below zero and never above 15 ...
countA = CountA + dirA Min 1 + dirA - 1 Max 15

This will roll-over, so 0 - 1 = 15, 15 + 1 = 0 ...
countA = countA + dirA + dirA - 1 & 15
Hi Hippy,
I added each of these methods into my existing code and it works well.

However, i noticed when trying to change the "Max 15" to anything higher, e.g. "Max 16" The code doesn't change the CountA or CountB values in the terminal. (FYI: going above Max 15 in earlier versions of the code works).
Is there something with the masking that is strictly only using the LSB nibble to access codes 0 to 15 and nothing higher?
I would find it handy to be able to set "Max" to 255, just so i have the flexibility to use any Max value in future.
Some of my coding often requires a max of 4, 8, 15 and perhaps 20, 32 or 64 in future.

Thanks in advance.
 

hippy

Technical Support
Staff member
However, i noticed when trying to change the "Max 15" to anything higher, e.g. "Max 16" The code doesn't change the CountA or CountB values in the terminal.
The limited to not going below zero nor above N should have worked for any value of N when using -
Rich (BB code):
countX = countX + dirX Min 1 + dirX - 1 Max N
But the roll-over version using '&' won't work when N is not 'a power of two less one' -
Rich (BB code):
countX = countX + dirX + dirX - 1 & N ; <-- Will not work for all values of N
Using 255 should have worked for the existing code because 255 is 'a power of two less one', 28-1, 256-1, but if wanting other values which aren't, 4, 8, 20 etc that has to be adjusted.

There may be some clever trick giving a one-liner for that but the best I can come up with off the top of my head is, for 20 here, untested -
Rich (BB code):
If dirX = 1 Then
  countX = countX + 1 // 21
Else
  countX = countX - 1 Max 20
End If
(FYI: going above Max 15 in earlier versions of the code works).
Only because the original code was using 255 and your code was using 15, which are both 'a power of two less one'.
 

OLDmarty

Senior Member
The limited to not going below zero nor above N should have worked for any value of N when using -
Rich (BB code):
countX = countX + dirX Min 1 + dirX - 1 Max N
But the roll-over version using '&' won't work when N is not 'a power of two less one' -
Rich (BB code):
countX = countX + dirX + dirX - 1 & N ; <-- Will not work for all values of N
Using 255 should have worked for the existing code because 255 is 'a power of two less one', 28-1, 256-1, but if wanting other values which aren't, 4, 8, 20 etc that has to be adjusted.

There may be some clever trick giving a one-liner for that but the best I can come up with off the top of my head is, for 20 here, untested -
Rich (BB code):
If dirX = 1 Then
  countX = countX + 1 // 21
Else
  countX = countX - 1 Max 20
End If

Only because the original code was using 255 and your code was using 15, which are both 'a power of two less one'.
Ahh, ok, fair enough.

So, my current code (Max 15) offers me 16 different patterns to send to the LED display, the reason i then tried to make it 'Max 16' was to add a 17th pattern, which would be all off ($00).

In your earlier coding, when i first made up my select..case routine, i used 16 cases, where '0' would blank the display, and '1' to '16' would be the required 16 patterns for the LEDS.

At the moment, with todays code, there are always a bar of 4 leds shown on the display, and never a display all off state..
I know i can always add another option to blank the display based on what mode or menu i have selected in the final project.

I'll keep tinkering, or revert to an earlier version of your code that works above '15', even if it isn't as 'reduced' as your later codes ;-)
 

hippy

Technical Support
Staff member
So, my current code (Max 15) offers me 16 different patterns to send to the LED display, the reason i then tried to make it 'Max 16' was to add a 17th pattern, which would be all off ($00).
Using MAX 16 should have worked, allowing you to change your count down to zero where it would stay if you tried to go lower, and up to 16 where it would stay if you tried to go higher.

Having 0 to 16 is the distinct 17 values you desire.

Post your full code so we can try and see where the issue is.
 

hippy

Technical Support
Staff member
Here's a one-liner which does roll-over so, 0 - 1 => 16, 16 + 1 => 0 -

countX = countX + bitX + bitX - 1 Max 33 // 17

Which, for a 0..N result, is derived from -

countX = countX + bitX + bitX - 1 Max (N*2+1) // (N+1)

So, no matter what your 0..N is ( up to N=32767) you can calculate N*2+1 and N+1 and drop that in the calculation.

The trickery is in letting the intermediate result become -1, which is actually a large positive number, 65535. Then limiting that to a maximum which, when the modulo is applied, will give us the result desired. N*2+1 is the smallest value which will do that which is above the legitimate values it could be when doing a plus one addition.
 

OLDmarty

Senior Member
Here's a one-liner which does roll-over so, 0 - 1 => 16, 16 + 1 => 0 -

countX = countX + bitX + bitX - 1 Max 33 // 17

Which, for a 0..N result, is derived from -

countX = countX + bitX + bitX - 1 Max (N*2+1) // (N+1)

So, no matter what your 0..N is ( up to N=32767) you can calculate N*2+1 and N+1 and drop that in the calculation.

The trickery is in letting the intermediate result become -1, which is actually a large positive number, 65535. Then limiting that to a maximum which, when the modulo is applied, will give us the result desired. N*2+1 is the smallest value which will do that which is above the legitimate values it could be when doing a plus one addition.

Hi Hippy,

Thanks, i'll try these new options in your most recent code when i'm back at work tomorrow.


Am i simply replacing the existing "count = count + bit +bit" equations? Are there any other symbol/variables that need to be renamed to match the new equations etc?

Thanks again.
 

hippy

Technical Support
Staff member
Am i simply replacing the existing "count = count + bit +bit" equations? Are there any other symbol/variables that need to be renamed to match the new equations etc?
Yes, and No, probably, though it depends on how you have currently implemented them.

If the calculation is in a macro using 'maxX' as previously suggested then you can't easily make that work using 'maxX' provided to the macro without calculating maxX*2+1 and maxX+1 at run-time without additional calculations which will slow processing down.

You might want to define your MAXB, then define MAXB_PLUS_1 and MAXB_TIMES_2_PLUS_1 with symbols. The best way to do that would probably be with -
Code:
Symbol MAXB                = 16 
Symbol MAXB_PLUS_1         = MAXB + 1
Symbol MAXB_TIMES_2        = MAXB * 2
Symbol MAXB_TIMES_2_PLUS_1 = MAXB_TIMES_2 + 1

countB = countB + bitB + bitB - 1 Max MAXB_TIMES_2_PLUS_1 // MAXB_PLUS_1
 

OLDmarty

Senior Member
Yes, and No, probably, though it depends on how you have currently implemented them.

If the calculation is in a macro using 'maxX' as previously suggested then you can't easily make that work using 'maxX' provided to the macro without calculating maxX*2+1 and maxX+1 at run-time without additional calculations which will slow processing down.

You might want to define your MAXB, then define MAXB_PLUS_1 and MAXB_TIMES_2_PLUS_1 with symbols. The best way to do that would probably be with -
Code:
Symbol MAXB                = 16
Symbol MAXB_PLUS_1         = MAXB + 1
Symbol MAXB_TIMES_2        = MAXB * 2
Symbol MAXB_TIMES_2_PLUS_1 = MAXB_TIMES_2 + 1

countB = countB + bitB + bitB - 1 Max MAXB_TIMES_2_PLUS_1 // MAXB_PLUS_1
Hi Hippy,
Previously i hadn't used your macro's code.

I have added your MAXB definitions, but i don't have a symbol for your "bitB" that's used in your one-liner equation.
 

OLDmarty

Senior Member
Yes, and No, probably, though it depends on how you have currently implemented them.

If the calculation is in a macro using 'maxX' as previously suggested then you can't easily make that work using 'maxX' provided to the macro without calculating maxX*2+1 and maxX+1 at run-time without additional calculations which will slow processing down.

You might want to define your MAXB, then define MAXB_PLUS_1 and MAXB_TIMES_2_PLUS_1 with symbols. The best way to do that would probably be with -
Code:
Symbol MAXB                = 16
Symbol MAXB_PLUS_1         = MAXB + 1
Symbol MAXB_TIMES_2        = MAXB * 2
Symbol MAXB_TIMES_2_PLUS_1 = MAXB_TIMES_2 + 1

countB = countB + dirB + dirB - 1 Max MAXB_TIMES_2_PLUS_1 // MAXB_PLUS_1
Hi Hippy, I changed to "dirB" and it seems fine as an endless counter 0 to N and repeating 0 to N....(and N to 0, repeating).

For the other option, to stop at N (stop at 16 and stop at 0), What do i need to change the equation to now?
I tried "countB = countB + dirB + dirB - 1 Max MAXB" which stops at 16, but doesn't stop at 0, repeating. I couldn't find a way to implement a 'min' in there. ;-(

with thanks
 

hippy

Technical Support
Staff member
As per earlier posts -

countB = countB + dirB Min 1 + dirB - 1 Max MAX_B
 

OLDmarty

Senior Member
As per earlier posts -

countB = countB + dirB Min 1 + dirB - 1 Max MAX_B
Ahh, thanks, my brain was hurting ;-)

Although i did manage to correct "MAX_B" to "MAXB" and it works now ;-)

Thanks again Hippy,
I greatly appreciate your efforts.
 

OLDmarty

Senior Member
Although i did manage to correct "MAX_B" to "MAXB" and it works now ;-)

Hi Hippy,

OK, so both encoders seem to be working to whatever 'N' i choose, based on your recent revised equations and symbol definitions.

However, on the odd occasion, sometimes moving Encoder A will affect the values being processed/displayed for Encoder B.

FYI:
Encoder A is adjusting the (2x) 7-Seg displays, while Encoder B is adjusting the 4-bit pattern that is assigned in the Select..Case routine.

I've only witnessed Encoder A adjusting B's info/display, but i've seen Encoder B adjusting A's info/display.
When i look at the terminal window, if i move encoder A, the B value isn't changing by 1's, it looks to be jumping by 4's

e.g.
A =1
B =4
A =2
B =8
A =3
B =12
A =4

Although, the B value doens't change on every change of A, so it's more like:


A =1
B =4
A =2
A =3
A =4
A =5
B = 8
A = 6
B = 12
A = 7
A = 8
A = 9
B = 16


The weird thing is, i cannot make this bug occur anytime i wish to.
It seems to happen only after powering ON the project, but a basic reset doesn't seem to make the bug come back.

So far, most times when i notice the bug, if i then move encoder B, then i find Encoder A no longer affects B anymore.

It seems i'm setting (or clearing) a bit (or variable) somewhere, but i can't see any anomalies in the code structure as yet.


UPDATE #### I just powered up the project again, and notice when adjusting encoder A, that going downwards from 1 to 16, (using the repeating equation) it actually nearly always goes to 11, then 16 appears on the next downward 'click'....very strange.



Code:
#PICAXE 40X2            ; Define PICAXE 40X2 type
#NO_DATA                ;Stop EEPROM data from being cleared during programming
#NO_TABLE                ;Ignore TABLE data - loads program faster
#Terminal 9600

;setfreq m16    ;ENABLE this when not using the serial terminal, for final product (sppeds up rotary pot reads and LED matrix updates).

;Initialize:                ' Initialise pins and set up variables
;Setup all the port bits to a clean state...
dirsA=$00:dirsB=$00:dirsC=$FF:dirsD=$00                ;11111111, Port C as OUTPUTS, Port A,B & D as INPUTS
outpinsA=$00:outpinsB=$00:outpinsC=$00:outpinsD=$00        ;00000000, clear ALL Port outputs to all 0's

;
Hi2cSETUP  i2cmaster,%11100000, i2cfast, i2cbyte
PAUSE 10 ; wait 1 ms for the display chip to initialise
Hi2cOUT ($21) ; start clock/oscillator
; $00 turns off the whole row
;

#Define PORT       D         ; D.x

;                   76543210
Symbol MASKA     = %00010000 ; D.4
Symbol MASKB     = %01000000 ; D.6

Symbol MASK      = %01010000 ; All the above

Symbol pinsX     = pinsD     ; D.x

Symbol clkA      = bit4      ; D.4
Symbol dirA      = bit5      ; D.5
Symbol clkB      = bit6      ; D.6
Symbol dirB      = bit7      ; D.7

Symbol reserveB0 = b0

Symbol countA    = b2
Symbol countB    = b3
Symbol lastA     = b4
Symbol lastB     = b5

Symbol ROW_1 = b23    ;RGB LEDS 1 & 2
Symbol ROW_2 = b24    ;RGB LEDS 1 & 2
Symbol ROW_3 = b25    ;RGB LEDS 1 & 2
Symbol ROW_4 = b26    ;RGB LEDS 1 & 2
Symbol ROW_5 = b27    ;RGB LEDS 1 & 2
Symbol ROW_6 = b28    ;RGB LEDS 1 & 2
Symbol ROW_7 = b29    ;RGB LEDS 1 & 2
Symbol ROW_8 = b30    ;RGB LEDS 1 & 2

Symbol _F0 = b40    ;RGB LEDS 1 & 2
Symbol _0F = b41    ;RGB LEDS 1 & 2

Symbol SEG7_1 = b31    ;SEG7-1 is the LEFT  side display, (the 10's column).
Symbol SEG7_2 = b32    ;SEG7-2 is the RIGHT side display. (the  1's column).


;######################
Symbol MAXB                = 17
Symbol MAXB_PLUS_1         = MAXB + 1        ;(e.g. 17)
Symbol MAXB_TIMES_2        = MAXB * 2        ;(e.g. 32)
Symbol MAXB_TIMES_2_PLUS_1 = MAXB_TIMES_2 + 1    ;(e.g. 33)


Symbol MAXA                = 17
Symbol MAXA_PLUS_1         = MAXA + 1        ;(e.g. 17)
Symbol MAXA_TIMES_2        = MAXA * 2        ;(e.g. 32)
Symbol MAXA_TIMES_2_PLUS_1 = MAXA_TIMES_2 + 1    ;(e.g. 33)
;#######################

Hi2cOUT ($80) ; clear the display
Hi2cOUT ($EF) ' set to full brightness

;CLEAR all the LED matrix rows to blank.
ROW_1 = $00 : ROW_2 = $00 : ROW_3 = $00 : ROW_4 = $00 : ROW_5 = $00 : ROW_6 = $00 : ROW_7 = $00 : ROW_8 = $00

;Setup the 2 different patterns for the Select..Case procedure.
_F0 = $F0    ;Pre-defined "$F0" value
_0F = $0F    ;Pre-defined "$0F" value



PowerOnReset:
  SerTxd( "Started", CR, LF )
  Gosub Interrupt_Enable

MainLoop:
  Do
    If countA <> lastA Then
      SerTxd( "A = ", #countA, CR, LF )
      lastA = countA
    End If
    If countB <> lastB Then
      SerTxd( "B = ", #countB, CR, LF )
      lastB = countB
    End If


  ;##################################################################
select case countb
    case  0 : gosub blankit
    case  1 : gosub blankit : ROW_1 = _F0    ;Set to Pre-defined value of "$F0"
    case  2 : gosub blankit : ROW_1 = _0F    ;Set to Pre-defined value of "$0F"
    case  3 : gosub blankit : ROW_2 = _F0  
    case  4 : gosub blankit : ROW_2 = _0F  
    case  5 : gosub blankit : ROW_3 = _F0  
    case  6 : gosub blankit : ROW_3 = _0F
    case  7 : gosub blankit : ROW_4 = _F0  
    case  8 : gosub blankit : ROW_4 = _0F
    case  9 : gosub blankit : ROW_5 = _F0
    case 10 : gosub blankit : ROW_5 = _0F
    case 11 : gosub blankit : ROW_6 = _F0  
    case 12 : gosub blankit : ROW_6 = _0F  
    case 13 : gosub blankit : ROW_7 = _F0  
    case 14 : gosub blankit : ROW_7 = _0F
    case 15 : gosub blankit : ROW_8 = _F0  
    case 16 : gosub blankit : ROW_8 = _0F
  
    case 17 : gosub blankit
endselect
;##################################################################

;  Get the 7-SEG display value(s) ###### 
      lookup countA,($30,$6D,$79,$33,$5B,$5F,$70,$7F,$7B,$7E,$30,$6D,$79,$33,$5B,$5F),SEG7_2    ;Load 7-SEG values onto 7-seg Display(s)
      if countA > 8 then        ; when 'counter'(lookup) becomes greater then the 9th digit (0 to 8, is 9 counts)...bring on the 10's digit for numbers 10 to 16.
       SEG7_1 = $30        ; Turn on the 10's digit (1) for numbers 10 to 16 on the LEFT 7-seg display.
       else seg7_1 = $00    ; if 'counter' is 9 or less, then turn OFF thge `10's digit (1) again, for numbers 1-9 in the RIGHT 7-seg display.
    endif

;  SEND_TO_8x8/7-SEG MATRIX ######
;                              |                   |                   |                   |                    |                     |                     |                    |
;          A0..A7  A8..A15  |  A0..A7  A8..A15  |  A0..A7  A8..A15  |  A0..A7  A8..A15  |  A0..A7   A8..A15  |  A0..A7    A8..A15  |  A0..A7    A8..A15  |  A0..A7    A8..A15 |
;                              |                   |                   |                   |                    |                     |                     |                    |
Hi2cOUT $00, (ROW_1, SEG7_1,            ROW_2,  SEG7_2,    ROW_3,    $00,      ROW_4, $00,          ROW_5,   $00,        ROW_6,   $00,         ROW_7,   $00,          ROW_8,   $00)
Hi2cOUT ($81) ; turn on the display


Loop



Interrupt:

  b0 = pinsX

  If clkA <> 0 Then
      countA = countA + dirA + dirA - 1 Max MAXA_TIMES_2_PLUS_1 // MAXA_PLUS_1 ; <--- Use this line for Counts 0 to 16 and repeats 0 to 16 endlessly, (or 16 to 0, repeats endlessly 16 to 0).
      ;countA = countA + dirA Min 1 + dirA - 1 Max MAXA    ; <--- Use this line for Counts 0 to 15 and STOPS at 16, (and 16 to 0 and STOPS at 0).
  End If

  If clkB <> 0 Then
      countB = countB + dirB + dirB - 1 Max MAXB_TIMES_2_PLUS_1 // MAXB_PLUS_1 ; <--- Use this line for Counts 0 to 16 and repeats 0 to 16 endlessly, (or 16 to 0, repeats endlessly 16 to 0).
      ;countB = countB + dirB Min 1 + dirB - 1 Max MAXB    ; <--- Use this line for Counts 0 to 15 and STOPS at 16, (and 16 to 0 and STOPS at 0).
  End If

  b0 = b0 And MASK
  SetInt Not b0, MASK, PORT
  Return

Interrupt_Enable:
  b0 = pinsX And MASK
  SetInt Not b0, MASK, PORT
  Return

blankit:
  ROW_1 = $00 : ROW_2 = $00 : ROW_3 = $00 : ROW_4 = $00 : ROW_5 = $00 : ROW_6 = $00 : ROW_7 = $00 : ROW_8 = $00
  return
 
Last edited:

hippy

Technical Support
Staff member
I cannot see any obvious reason that it wouldn't keep accurate count or why one would interact with the other.

Does it work correctly when you remove your display interfacing code ?

It could be because you are updating your displays every loop rather than only when the values have changed.
 
Top