Using XOR to convert a Graycode Encoder

(instructions, reset, WDT, specifications...) PIC17Cxx, PIC18Fxxx

Using XOR to convert a Graycode Encoder

Postby GettinBetter » Sun Jul 28, 2019 3:42 pm

Setup:
EasyPIC V7 board/ICD3/MCC
Using PIC18F45K22/8MHz
XC8/C90

Continuing on the same project http://picforum.ric323.com/viewtopic.php?f=32&t=735 but a different subject (it was getting off topic).
My research leads me to think I need to XOR the input from the encoder. From what I've done so far (created a excel spreadsheet to convert gray to binary & hex) it seems that each capture of the 10 pins needs 10 iterations of the XOR to create a converted hex value.
My question is:
Can I just apply the XOR to the 16bit value (something like below), because its taken care of in the background, or will i need to create a loop to iterate through the bits.

Code: Select all
    Volatile int GC_Raw = 0000000000001100; // set/change  values for testing
    Volatile int Binary_XORd = 0000000000000000;

    void main (void)
    while
    {
    //GC_Raw = PORTB; // Use when tested
    Binary_XORd = Binary_XORd ^ GC_Raw ;
    printf("Binary value:  %d",Binary_XORd);
    }



Regards
Les
History teaches us that history doesn't teach us.
User avatar
GettinBetter
 
Posts: 17
Joined: Wed Jun 06, 2018 8:48 pm

Re: Using XOR to convert a Graycode Encoder

Postby AussieSusan » Mon Jul 29, 2019 3:34 am

I'm not really sure that I understand either your problem or your solution.
the XOR operation will work on whatever sized values you use. If the are 16-bit then you will get a result that is the XOR operation or each of the 16 pairs of bits you start with.
Also,what are you expecting to see as the output of your code snippet?
What you WILL get is the output value alternating between 12 and 0!
Do you understand the XOR operation?
Do you understand the grey to binary conversion algorithm?
Susan
AussieSusan
Verified identity
 
Posts: 110
Joined: Mon Jun 16, 2014 4:45 am
PIC experience: Experienced Hobbyist

Re: Using XOR to convert a Graycode Encoder

Postby ric » Mon Jul 29, 2019 2:03 pm

I suspect Les does not understand the algorithm.
All the algorithms I have seen described only ever talk about XORing a single bit at a time. There's no way to do them all at once, because what do do depends upon the state of the previous bit.
e.g. from https://www.geeksforgeeks.org/gray-to-b ... onversion/
Gray to binary conversion :

The Most Significant Bit (MSB) of the binary code is always equal to the MSB of the given binary number.
Other bits of the output binary code can be obtained by checking gray code bit at that index. If current gray code bit is 0, then copy previous binary code bit, else copy invert of previous binary code bit.


However, there is a quicker way to do it. I tested the technique described at http://dspguru.com/dsp/tricks/gray-code-conversion/ using an Excel spreadsheet, and it works!
Latest test project, an LED matrix display made from one reel of addressable LEDs. here
User avatar
ric
Verified identity
 
Posts: 500
Joined: Sat May 24, 2014 2:35 pm
Location: Melbourne, Australia
PIC experience: Professional 5+ years with MCHP products

Re: Using XOR to convert a Graycode Encoder

Postby GettinBetter » Sat Aug 03, 2019 3:01 pm

Finally got back on this....connecting the encoder took longer than anticipated, and I didn't get the led confirmation on the dev board that I was expecting so wired up the other encoder as well which gave exactly the same results, so I figured it's some internal wizardry inside the encoder that does that.

With the basic 8bit encoder that I practiced on it caused the leds on the dev boards to light as you rotated the spindle, obviously the patterns looked haphazard due to the binary input, but they were all bright and clearly going full on & full off. However with the 10bit encoders there are large blank areas of rotation where none of the leds are illuminated (roughly 30 degrees or so) them a bright full on/off area (60ish degrees), and also a dim on/off area (60ish degrees). this repeats twice though a full revolution, which I thought was odd, hence I wired the other one as well, but its the same.

I do understand the concept, and I did say I'd created an excel spreadsheet in my earlier post just to confirm my grasp...I did a degree in electronics some time ago, and remember gates etc, but knowing they exist is one thing, getting them to work is another. So I spent the day going over it all.
There's no way to do them all at once, because what do do depends upon the state of the previous bit.
hence I was asking about looping it through, but I was sure there'd be a simpler way, as you went on to prove.

So I'm here at the moment using the link that ric previously posted.....although now I'll be back at converting the binary to hex again...
And here as mention above isn't working.....I get the first bit of text with the program info and the text that reads "Binary Output:" but when I turn the spindle nothing...

Code: Select all
    volatile uint8_t G_PortB;
    volatile uint8_t G_PortC_0;
    volatile uint8_t G_PortC_1;
    volatile uint16_t GrayInput;
    unsigned short temp;
    unsigned short num;
    unsigned short Result;
   
unsigned short grayToBinary(unsigned short num)
{
    unsigned short temp = num ^ (num>>8);  //short =16bits
            temp ^= (temp>>8);
            temp ^= (temp>>4);
            temp ^= (temp>>2);
            temp ^= (temp>>1);
    return temp;
}   

   
void main(void)
{
    // Initialize the device
    SYSTEM_Initialize();
    PIN_MANAGER_Initialize();
    INTERRUPT_Initialize();
    EUSART1_Initialize();

    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();

void EUSART1_Initialize(void);
{
   
    printf("\rEasyPIC V7-8MHz Date 03/08/2019\r\n"); 
    printf("USART Communications 8-bit Rx & Tx\r\n\n");
    printf("10bit Encoder to port B(0:7) & PortC(0:1)\r\n\n");
    printf("DIPS set to pull down. \r\n\n");
}

    while (1)
    {   
    G_PortC_0 = IO_RC0_PORT;        //Pin RC0 Single bit Binary Input
    G_PortC_1 = IO_RC1_PORT;        //Pin RC1    Single bit Binary Input
    G_PortB = PORTB;               //Pin RB0-7 8 bit Binary Input
    GrayInput = (G_PortC_0<<2 | G_PortC_1<<1 | PORTB);     //shift G_PortC to become bit9 of GrayInput, shift G_PortC to become bit8 of GrayInput  add all of PortB
   
    Result =grayToBinary(GrayInput);

    printf("Binary Output:  \r",Result);
}
/**
 End of File
*/
}


...and this is the terminal output

EasyPIC V7-8MHz Date 03/08/2019
USART Communications 8-bit Rx & Tx

10bit Encoder to port B(0:7) & PortC(0:1)

DIPS set to pull down.

Binary Output:


I'm very confused about the right shifting of the bits...
Code: Select all
unsigned short temp = num ^ (num>>8)

(stop me if I'm wrong) is num xored with the previous value of num, but how is num (16bit) shifted 8 positions, and why?
would you be kind enough to explain what's going at this point?
Is it something to do with the way the variable is populated, i.e. LSB first...

Regards
Les
History teaches us that history doesn't teach us.
User avatar
GettinBetter
 
Posts: 17
Joined: Wed Jun 06, 2018 8:48 pm

Re: Using XOR to convert a Graycode Encoder

Postby GettinBetter » Sun Aug 04, 2019 8:04 am

Ok, So I finally got an output, although its not making any sense at the moment. However we are moving forward. Here's the code.

Code: Select all
    volatile uint8_t G_PortB;
    volatile uint8_t G_PortC_0;
    volatile uint8_t G_PortC_1;
    volatile uint16_t GrayInput;
    volatile uint16_t TwoBitsCombined;
    volatile uint16_t TwoBitsCombined_Shifted;
    unsigned short temp;
    unsigned short num;
    unsigned short Gray2BinOutput;
   
unsigned short grayToBinary(unsigned short num)
{
    unsigned short temp = num ^ (num>>8);  //still not sure whats going on here
            temp ^= (temp>>4);
            temp ^= (temp>>2);
            temp ^= (temp>>1);
    return temp;
}   
   
void main(void)
{
    // Initialize the device
    SYSTEM_Initialize();
    PIN_MANAGER_Initialize();
    INTERRUPT_Initialize();
    EUSART1_Initialize();

void EUSART1_Initialize(void);

    printf("\rEasyPIC V7-8MHz Date 03/08/2019\r\n"); 
    printf("USART Communications 8-bit Rx & Tx\r\n\n");
    printf("10bit Encoder to port B(0:7) & PortC(0:1)\r\n\n");
    printf("DIPS set to pull down. \r\n\n");
}

    while (1)
    {
    G_PortC_0 = IO_RC0_PORT;                    //Pin RC0 Single bit Binary Input (sends to rightermost bit0)
        // 00000001 what I think would be the result assuming all pins are high
    G_PortC_0 = G_PortC_0<<1;                   //shift RC0bit to bit1
        // 00000010 what I think would be the result assuming all pins are high
    G_PortC_1 = IO_RC1_PORT;                    //Pin RC1 Single bit Binary Input (sends to rightermost bit0)
    TwoBitsCombined = G_PortC_0|G_PortC_1;        //
        // 0000000000000011  what I think would be the result assuming all pins are high
    TwoBitsCombined_Shifted = TwoBitsCombined<<8;
        // 0000001100000000   what I think would be the result assuming all pins are high
    G_PortB = PORTB;                            //Pin RB0-7 8bit Binary Input
        // Result 11111111
    GrayInput = (TwoBitsCombined_Shifted | PORTB);   //OR the above together
        // 0000001111111111 what I think would be the result assuming all pins are high
   
    Gray2BinOutput =grayToBinary(GrayInput);

    printf("\rBinary Output:  %d",Gray2BinOutput);
}
}
/**
 End of File
*/


Would like to understand this "unsigned short temp = num ^ (num>>8);" if I'm passing in this '0000001111111111' and the brackets get done first, then I'm left with '0000000000000011' which is then xor'd with the original num, is that right?

Output ranges from 0019 to 9990 some parts are incremental others are what seems random, but what is more worrying is that the blank spots are still there!!

As usual your comments are invited.

Regards
Les
History teaches us that history doesn't teach us.
User avatar
GettinBetter
 
Posts: 17
Joined: Wed Jun 06, 2018 8:48 pm

Re: Using XOR to convert a Graycode Encoder

Postby AussieSusan » Mon Aug 05, 2019 3:40 am

That code, as shown, does not really make a lot of sense to me.
Is the 'EUSART1_Initialize() function inside the 'main' function? If so it should not be - move it somewhere on its own as many compilers for embedded devices don;t allow nested functions.
What is the 'EUSART1_Initialize()' function supposed to do? It certainly does not do what the name suggests which is to initialise EUSART1. In fact, if the 'printf' setup is to use this EUSART to output characters then you will see nothing as the EUSART has not been configured in the coder you have provided.
I think you are trying to do too much at once right now. Personally, I would spend a bit of time with a pencil and (lots of) paper to work out how the grey-to-binary conversion works.
Next get the code to output some pre-defined numbers to make sure that this part of the code is working as you expect.
Next read in the grey code from the port and just output that. As it is grey code, the numbers will jump around but that is to be expected.
Finally, code up the grey-to-binary code that you have worked out at the start and insert that.
By following this approach you will not only come to understand how the grey-to-binary algorithm works, you can also be sure that each part of the code is built on top of code that you know is working correctly. If something is not working as it should, then the problem is in the last bit of code that you added, so this makes the debugging tasks a whole lot easier.
Susan
AussieSusan
Verified identity
 
Posts: 110
Joined: Mon Jun 16, 2014 4:45 am
PIC experience: Experienced Hobbyist

Re: Using XOR to convert a Graycode Encoder

Postby Roche » Mon Aug 05, 2019 9:52 am

Possibly build and test the Gray to Binary converter in a simulator, so you can see what is happening step by step.
Roche
 
Posts: 43
Joined: Fri Jul 11, 2014 12:35 pm
PIC experience: Professional 5+ years with MCHP products

Re: Using XOR to convert a Graycode Encoder

Postby Roche » Tue Aug 06, 2019 2:51 pm

This sort of got me intrigued. I only work in assembly - this seems to work OK:
Code: Select all
;------------------------------------------------------------------------------
;gray
; Converts 8 bit gray code to binary
; can almost certainly be optimised - takes about 91 +/- instructions to execute
; Uses 3 8 bit registers
;      input      ; input gray code
;      output      ; output binary
;      count       ; loop count
;------------------------------------------------------------------------------
gray:                  ; 8 bit gray to binary converter
   movlw   0x08         ; initialise loop count
   movwf   count

   clrf   output         ; clear the output

   btfsc   input, 7      ; test most significant bit
   bsf      output, 7

gray10:
   decfsz   count         ; loop until done
   bra      grayloop

   rlncf   input         ; preserve the input
   rlncf   output         ; final rotation
   return

grayloop:
   rlncf   input         ; all operations are on the most significant bit of input and output
   btfss   output, 7      ; which are rotated to evaluate each bit.
   bra      grayloop10
   rlncf   output
   btfss   input, 7
   bsf      output, 7
   bra      gray10
grayloop10:
   rlncf   output
   btfsc   input, 7
   bsf      output, 7
   bra      gray10
;------------------------------------------------------------------------------


I'm sure there are ways to improve it...

Regards,

Roche
Roche
 
Posts: 43
Joined: Fri Jul 11, 2014 12:35 pm
PIC experience: Professional 5+ years with MCHP products

Re: Using XOR to convert a Graycode Encoder

Postby GettinBetter » Fri Aug 09, 2019 9:36 pm

Roche wrote:This sort of got me intrigued. I only work in assembly - this seems to work OK:
Code: Select all
;------------------------------------------------------------------------------
;gray
; Converts 8 bit gray code to binary
; can almost certainly be optimised - takes about 91 +/- instructions to execute
; Uses 3 8 bit registers
;      input      ; input gray code
;      output      ; output binary
;      count       ; loop count
;------------------------------------------------------------------------------
gray:                  ; 8 bit gray to binary converter
   movlw   0x08         ; initialise loop count
   movwf   count

   clrf   output         ; clear the output

   btfsc   input, 7      ; test most significant bit
   bsf      output, 7

gray10:
   decfsz   count         ; loop until done
   bra      grayloop

   rlncf   input         ; preserve the input
   rlncf   output         ; final rotation
   return

grayloop:
   rlncf   input         ; all operations are on the most significant bit of input and output
   btfss   output, 7      ; which are rotated to evaluate each bit.
   bra      grayloop10
   rlncf   output
   btfss   input, 7
   bsf      output, 7
   bra      gray10
grayloop10:
   rlncf   output
   btfsc   input, 7
   bsf      output, 7
   bra      gray10
;------------------------------------------------------------------------------


I'm sure there are ways to improve it...

Regards,

Roche


That's interesting, is this something you've just created, and I assume you tested it? I don't know anything about assembly, but am aware it's possible to insert it into a 'C' file. The encoder I'm using is a 10bit so am using a 16bit var to concatenate both ports pins. Trouble is, the output is binary so there's still work to do on each value to convert to hex.

I took onboard what you guys are saying, I'll make an effort to learn to use the simulator and/or debugging options and break it into smaller parts proving each section.

It's still bugging me though, as to why the encoder has blank spots!

Regards
Les
History teaches us that history doesn't teach us.
User avatar
GettinBetter
 
Posts: 17
Joined: Wed Jun 06, 2018 8:48 pm

Re: Using XOR to convert a Graycode Encoder

Postby Roche » Sat Aug 10, 2019 10:05 am

I did just write it. I've plugged some values into it in the simulator. I haven't tested it at every value... It would be reasonably easy to to expand to 16 bit, just need to rotate the two bytes rather than one as at present. I would treat the binary to hex conversion as a separate task - I guess that's for display purposes.

As to blank spots, We would probably need more information.

Regards,

Roche
Roche
 
Posts: 43
Joined: Fri Jul 11, 2014 12:35 pm
PIC experience: Professional 5+ years with MCHP products

Next

Return to 16-Bit Core

Who is online

Users browsing this forum: No registered users and 2 guests