Jump to content

Encoder direction


DriftZ
 Share

Recommended Posts

Hi,

you can change the direction by inverting the incrementer value in USER_ENC_NotifyChange.

Example (not checked)

USER_ENC_NotifyChange
        ;; inverting the incrementer:
        ;; if negative: incrementer = NOT incrementer
        ;; if positive: incrementer = (NOT incrementer) + 1
        comf    MIOS_PARAMETER2, W
        IFCLR   MIOS_PARAMETER2, 7, addlw 1 
        movwf   MIOS_PARAMETER2  

        ;; continue...

Best Regards, Thorsten.

Link to comment
Share on other sites

  • 3 years later...

Sorry to drag this topic from the deep & dark vaults, but how does one do this now that the code has changed to this:

USER_ENC_NotifyChange
	extern	_ENC_NotifyChange

	lfsr	FSR0, STACK_HEAD	; initialize stack
	lfsr	FSR2, STACK_HEAD

	movff	MIOS_PARAMETER2, POSTDEC0
	;; encoder number still in WREG
	goto	_ENC_NotifyChange

Link to comment
Share on other sites

So yours looks like this:

USER_ENC_NotifyChange

        ;; inverting the incrementer:
        ;; if negative: incrementer = NOT incrementer
        ;; if positive: incrementer = (NOT incrementer) + 1
        comf    MIOS_PARAMETER2, W
        IFCLR   MIOS_PARAMETER2, 7, addlw 1 
        movwf   MIOS_PARAMETER2  

        ;; continue...

	extern	_ENC_NotifyChange

	lfsr	FSR0, STACK_HEAD	; initialize stack
	lfsr	FSR2, STACK_HEAD

	movff	MIOS_PARAMETER2, POSTDEC0
	;; encoder number still in WREG
	goto	_ENC_NotifyChange

Right? Edit: Oh yeh that's gonna screw with the encoder number in W.... Uhm.. Wow this post is old... Gimme a minute here to whip something up in ASM just for the archives... Of course in your case you can do it within the application... In main.c just do:
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when an encoder has been moved
// incrementer is positive when encoder has been turned clockwise, else
// it is negative
/////////////////////////////////////////////////////////////////////////////
void ENC_NotifyChange(unsigned char encoder, char incrementer) __wparam
{
  incrementer *= -1;
  unsigned int value;

  // encoder 0 is used to control the BPM
  if( encoder == 0 ) {
    value = (unsigned int)MCLOCK_BPMGet() - 48;
    if( MIOS_HLP_16bitAddSaturate(incrementer, &value, 255 - 48) ) {
      MCLOCK_BPMSet((unsigned char)value + 48);
      app_flags.DISPLAY_UPDATE_REQ = 1;
    }
  }
}

Link to comment
Share on other sites

OK I am not well right now so I make no promises, however... Try this if you want the ASM version.

It's pretty simple, the encoder number is restored from MIOS_PARAMETER1 to W. This is necessary because the ENC_NotifyChange funtion uses the __wparam option which means that the first parameter is passed using WREG.

USER_ENC_NotifyChange

	extern	_ENC_NotifyChange

        ;; inverting the incrementer:
        ;; if negative: incrementer = NOT incrementer
        ;; if positive: incrementer = (NOT incrementer) + 1
        comf    MIOS_PARAMETER2, W
        IFCLR   MIOS_PARAMETER2, 7, addlw 1 
        movwf   MIOS_PARAMETER2  

        ;; continue...

	lfsr	FSR0, STACK_HEAD	; initialize stack
	lfsr	FSR2, STACK_HEAD

	movff	MIOS_PARAMETER2, POSTDEC0

	;; put encoder number back in WREG
        movf    MIOS_PARAMETER1, W

	goto	_ENC_NotifyChange

Link to comment
Share on other sites

So yours looks like this:

No, unless I'm missing something, it doesn't look like that at all.

Here's the whole section:

;; --------------------------------------------------------------------------
;;  This function is called by MIOS when an encoder has been moved
;;  Input:
;;     o Encoder number in WREG and MIOS_PARAMETER1
;;     o signed incrementer value in MIOS_PARAMETER2:
;;       - is positive when encoder has been turned clockwise
;;       - is negative when encoder has been turned counter clockwise
;; --------------------------------------------------------------------------
USER_ENC_NotifyChange
	extern	_ENC_NotifyChange

	lfsr	FSR0, STACK_HEAD	; initialize stack
	lfsr	FSR2, STACK_HEAD

	movff	MIOS_PARAMETER2, POSTDEC0
	;; encoder number still in WREG
	goto	_ENC_NotifyChange


So there's nothing that resembles "IFCLR  MIOS_PARAMETER2, 7, addlw 1"

Link to comment
Share on other sites

That IFCLR is part of TK's code... Let me start from the beginning to make more sense ;)

BTW, in your case, you can skip right to the end if you do'nt care for technical stuff.....

OK MIOS will detect the movement of the encoder and report it to the application by calling USER_ENC_NotifyChange. It has two values: the encoder number; and a number to show how much the encoder has changed, and in which direction.

USER_ENC_NotifyChange is a part of the application. It is always in ASM.

In the case of the C application, the function is in mios_wrapper.asm. It makes a few small preparations and then it calls the ENC_NotifyChange (Note the missing 'USER_' in the name) function in the main.c file.

Because of this, you can change the encoder value either:

In your ASM or INC file, for ASM based apps (MB64E, MBSEQ, MBSID),

In the mios_wrapper.asm file, for C based applications (Clockbox), or...

In the main.c file, for C based applications (Clockbox)

Now, to invert the encoder is simple in C, so the third option is the easiest. The incrementer value and direction is saved in a value named...wait for it... 'incrementer'. you need to add

  incrementer *= -1;
In......
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when an encoder has been moved
// incrementer is positive when encoder has been turned clockwise, else
// it is negative
/////////////////////////////////////////////////////////////////////////////
void ENC_NotifyChange(unsigned char encoder, char incrementer) __wparam
{
<---------------------------------------------------------------------------------------HERE!!!!!!!!!!!!!!!
  unsigned int value;

  // encoder 0 is used to control the BPM
  if( encoder == 0 ) {
    value = (unsigned int)MCLOCK_BPMGet() - 48;
    if( MIOS_HLP_16bitAddSaturate(incrementer, &value, 255 - 48) ) {
      MCLOCK_BPMSet((unsigned char)value + 48);
      app_flags.DISPLAY_UPDATE_REQ = 1;
    }
  }
}
If you prefer, you can do it in ASM. This means altering your application's ASM or INC file - in the case of the C wrapper it is mios_wrapper.asm You need to add TK's code:
        ;; inverting the incrementer:
        ;; if negative: incrementer = NOT incrementer
        ;; if positive: incrementer = (NOT incrementer) + 1
        comf    MIOS_PARAMETER2, W
        IFCLR   MIOS_PARAMETER2, 7, addlw 1 
        movwf   MIOS_PARAMETER2  

        ;; continue...
In....
;; --------------------------------------------------------------------------
;;  This function is called by MIOS when an encoder has been moved
;;  Input:
;;     o Encoder number in WREG and MIOS_PARAMETER1
;;     o signed incrementer value in MIOS_PARAMETER2:
;;       - is positive when encoder has been turned clockwise
;;       - is negative when encoder has been turned counter clockwise
;; --------------------------------------------------------------------------
USER_ENC_NotifyChange
	extern	_ENC_NotifyChange
<---------------------------------------------------------------------------------------HERE!!!!!!!!!!!!!!!
	lfsr	FSR0, STACK_HEAD	; initialize stack
	lfsr	FSR2, STACK_HEAD

	movff	MIOS_PARAMETER2, POSTDEC0
	;; encoder number still in WREG  <--------------------------------------------------NOT TRUE!!!!!!!!!!!!!!!
	goto	_ENC_NotifyChange
Notice that my note mentions that the encoder number is not in WREG. W was manipulated by TK's code. (Note - the encoder number did not always go in W, this code from TK is for an older version of MIOS) WREG is needed to pass to the C function's 'unsigned char encoder' because the C function is forced to do so by the ' __wparam' at the end of the function definition. To fix this, we need to get the encoder number, which is fortunately still stored in MIOS_PARAMETER1, and move it to 'W'. You should change it so that instead of this:
	;; encoder number still in WREG  <--------------------------------------------------NOT TRUE!!!!!!!!!!!!!!!
	goto	_ENC_NotifyChange
it looks like this:
	;; put encoder number back in WREG
        movf    MIOS_PARAMETER1, W

	goto	_ENC_NotifyChange

The end product of all these can be seen en the last two posts.

Hope that helps!

Link to comment
Share on other sites

First of all, thanks for taking the time to help me out with this :) I appreciate it!

That IFCLR is part of TK's code... Let me start from the beginning to make more sense ;)

I gathered as much :)

Ok -

Re. C encoder reverse:

  incrementer *= -1;
This creates a syntax error: "token -> unsigned" Re. ASM encoder reverse:
IFCLR   MIOS_PARAMETER2, 7, addlw 1 

This line also creates a syntax error.

Am I doing something wrong here? Although I'm a C newbie (but not to programming in general), I understand exactly what you're trying to do.

Link to comment
Share on other sites

  incrementer *= -1;
This creates a syntax error: "token -> unsigned"
Ahh OK... About the C thing, that will be my poor excuse for C code. Can one of you C gurus take a look?
Re. ASM encoder reverse:
IFCLR   MIOS_PARAMETER2, 7, addlw 1 
This line also creates a syntax error.
Seems it didn't like us using the macro there. Try this (compiles OK for me)
USER_ENC_NotifyChange
	extern	_ENC_NotifyChange

	      ;; inverting the incrementer:
        ;; if negative: incrementer = NOT incrementer
        ;; if positive: incrementer = (NOT incrementer) + 1
        comf    MIOS_PARAMETER2, W

        ;;IFCLR   MIOS_PARAMETER2, 7, addlw 1 
        btfss	MIOS_PARAMETER2, 7
        addlw 1 
        movwf   MIOS_PARAMETER2  

        ;; continue...

	lfsr	FSR0, STACK_HEAD	; initialize stack
	lfsr	FSR2, STACK_HEAD

	movff	MIOS_PARAMETER2, POSTDEC0
	;; put encoder number back in WREG
        movf    MIOS_PARAMETER1, W

	goto	_ENC_NotifyChange

Link to comment
Share on other sites

Wow when I screw up I reallllly screw up! Sorry man.. WTF is going on here...

Problem is that I rarely deal with signed values at the binary level, I have to do some homework here...

I have just read the datasheet and the only mention of signed arithmetic is a two's complement system. wikipedia says:

Negating a number (whether negative or positive) is done by inverting all the bits and then adding 1 to that result

So if I can believe that, this should work:

USER_ENC_NotifyChange
	extern	_ENC_NotifyChange

	;; inverting the incrementer:
        ;; incrementer = (NOT incrementer) + 1 
        ;; aka 2s complement

        comf    MIOS_PARAMETER2, W
        addlw 1 
        movwf   MIOS_PARAMETER2  

        ;; continue...

	lfsr	FSR0, STACK_HEAD	; initialize stack
	lfsr	FSR2, STACK_HEAD

	movff	MIOS_PARAMETER2, POSTDEC0
	;; put encoder number back in WREG
        movf    MIOS_PARAMETER1, W

	goto	_ENC_NotifyChange
I still think that this change should be done within the application, in C, in which case we could try the same trick...
/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when an encoder has been moved
// incrementer is positive when encoder has been turned clockwise, else
// it is negative
/////////////////////////////////////////////////////////////////////////////
void ENC_NotifyChange(unsigned char encoder, char incrementer) __wparam
{
  incrementer = (!incrementer)+1  //invert encoder direction by 2's complement
  unsigned int value;

  // encoder 0 is used to control the BPM
  if( encoder == 0 ) {
    value = (unsigned int)MCLOCK_BPMGet() - 48;
    if( MIOS_HLP_16bitAddSaturate(incrementer, &value, 255 - 48) ) {
      MCLOCK_BPMSet((unsigned char)value + 48);
      app_flags.DISPLAY_UPDATE_REQ = 1;
    }
  }
}

Link to comment
Share on other sites

aha! i got your first C example to work :)

here's what the problem was:

when i did this it produced an error:

  
incrementer *= -1;
unsigned int value;
however, when I changed the order it worked:
  unsigned int value;
  incrementer *= -1;

thanks so much for your perseverence on this, stryd_one!!

Link to comment
Share on other sites

when i did this it produced an error:

  
incrementer *= -1;
unsigned int value;
however, when I changed the order it worked:
  unsigned int value;
  incrementer *= -1;

WTF!?!?

I have noticed that SDCC is real picky about where you declare stuff.... Maybe it won't let you declare once the funciton has begun? Hmmm...

Hey, whatever works! ;)

Glad it's behaving ;D

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...