• AVR Freaks

AnsweredHot!Difference between capture and compare modes with examples

Page: << < ..111213 Showing page 13 of 13
Author
eagle1
Super Member
  • Total Posts : 341
  • Reward points : 0
  • Joined: 2014/11/02 03:04:06
  • Location: Saudi Arabia
  • Status: offline
Re: I want to know the difference between capture and compare modes with examples 2018/07/30 09:46:26 (permalink)
0
1and0
Perhaps this one will be more explicit:
 
 
 
See above diagram.

Yes it's clear that it's LSB first ... now it's getting more confusing! I was happy that I did it, but now I don't know how my code is actually working!


.... The explanation I'm think of now, is that with my code, I'm actually reading the inverted bytes!
 
But the question that comes, it why it didn't work in the other way? If I could read the inverted bytes, then I should read the original non-inverted bytes?
 
1and0
eagle1
So I either have only two solutions:

Both your solutions do MS bit first. :(



Yeah but it's the only one worked for me. Doing the LSB first gave me 0xffffff00 for all the buttons!
 
If you wanted to decode this NEC, how would you do it?
 
1and0
Access is Denied
  • Total Posts : 9297
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: I want to know the difference between capture and compare modes with examples 2018/07/30 11:04:32 (permalink)
+1 (1)
eagle1
If you wanted to decode this NEC, how would you do it?

Here's my first attempt and it is untested:
#define NEC_Pin PORTDbits.RD2
uint8_t ReadNEC(void)
{
  uint16_t timer1;

  // Check 9 ms pulse
  WRITETIMER1(0);
  do {
    timer1 = READTIMER1();
    if (timer1 > 10000) return 0;
  } while (!NEC_Pin);
  if (timer1 < 8000) return 0; // NEC protocol?

  // Check 4.5 ms space
  WRITETIMER1(0);
  do {
    timer1 = READTIMER1();
    if (timer1 > 5000) return 0;
  } while (NEC_Pin);
  if (timer1 < 4000) return 0; // NEC protocol?

  // Read code message (32-bit)
  uint8_t i = 32;
  do {
    // Check 562.5 us pulse
    WRITETIMER1(0);
    do {
      timer1 = READTIMER1();
      if (timer1 > 700) return 0;
    } while (!NEC_Pin);
    if (timer1 < 400) return 0; // NEC protocol?

    // Check 562.5 us or 1687.5 us space
    WRITETIMER1(0);
    do {
      timer1 = READTIMER1();
      if (timer1 > 2000) return 0;
    } while (NEC_Pin);
    if (timer1 < 400) return 0; // NEC protocol?

    ir_code >>= 1; // Default bit = 0
    if (timer1 > 1000) // If space > 1 ms, bit = 1
      ir_code |= (1UL << 31);
  } while (--i);
  return 1;
}

PStechPaul
Super Member
  • Total Posts : 2294
  • Reward points : 0
  • Joined: 2006/06/27 16:11:32
  • Location: Cockeysville, MD, USA
  • Status: offline
Re: I want to know the difference between capture and compare modes with examples 2018/07/30 13:33:15 (permalink)
+1 (1)
I know my code also produced the word with the bits in reverse order, but it just seemed more efficient with just a single shift instead of shifting by as many as 31 times. It may be even more efficient to set up an array of four bytes to hold the address, inverse address, data, and inverse data. This must be done anyway, so why not in this function?
 
Another method would be to use a 32 bit mask that starts as 0b1000000000000000. As each bit is detected, OR the mask with the ir_code variable (if it is a "1"), and shift the mask right by one place each iteration. This will produce a 32 bit word with LSB MSB first and LSB last. However, the address and data bytes will be reversed.
 
[edit] You want the MSB first.
post edited by PStechPaul - 2018/07/30 16:28:45

 
1and0
Access is Denied
  • Total Posts : 9297
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: I want to know the difference between capture and compare modes with examples 2018/07/30 13:49:17 (permalink)
+1 (1)
PStechPaul
I know my code also produced the word with the bits in reverse order, but it just seemed more efficient with just a single shift instead of shifting by as many as 31 times.

Your code in Post #228 is NOT doing a single shift, it performs a shift for each bit as well.
 

It may be even more efficient to set up an array of four bytes to hold the address, inverse address, data, and inverse data. This must be done anyway, so why not in this function?

Make ir_code a union of four bytes.
 
 
Another method would be to use a 32 bit mask that starts as 0b1000000000000000. As each bit is detected, OR the mask with the ir_code variable (if it is a "1"), and shift the mask right by one place each iteration. This will produce a 32 bit word with LSB first.

Shifting this mask is no difference to shifting ir_code. <edit> Plus, you would need an additional 32-bit variable to hold this mask. </edit>
 
 
BUT, actually, you want the MSB first, so the original code was correct.

According to the various diagrams, it is LSb first.
post edited by 1and0 - 2018/07/30 14:07:14
DarioG
Allmächtig.
  • Total Posts : 54081
  • Reward points : 0
  • Joined: 2006/02/25 08:58:22
  • Location: Oesterreich
  • Status: offline
Re: I want to know the difference between capture and compare modes with examples 2018/07/30 14:15:22 (permalink)

GENOVA :D :D ! GODO
PStechPaul
Super Member
  • Total Posts : 2294
  • Reward points : 0
  • Joined: 2006/06/27 16:11:32
  • Location: Cockeysville, MD, USA
  • Status: offline
Re: I want to know the difference between capture and compare modes with examples 2018/07/30 16:48:03 (permalink)
0
I have corrected my cranial flatus in post #243.
 
What I meant was that the mask would be shifted just one place for each iteration of the loop, whereas shifting the 32 bit ir_code variable would require a loop with LSLF or LSRF as many as 31 times to get 1UL << 31. Also, shifting a 32 bit word requires four byte-wise shifts for each operation.
 
Parsing the received bit stream into four bytes would require only a single LSLF or LSRF operation for each iteration, and will result in the four bytes of address and data. That would also only require an 8 bit mask.
 
You could also just conditionally OR the ir_code variable with 0x800000 when a "1" is detected, and shift right once for each operation.
 
This is an interesting project, and I might build an IR receiver and see what comes out of my remotes.
post edited by PStechPaul - 2018/07/30 16:53:59

 
1and0
Access is Denied
  • Total Posts : 9297
  • Reward points : 0
  • Joined: 2007/05/06 12:03:20
  • Location: Harry's Gray Matter
  • Status: offline
Re: I want to know the difference between capture and compare modes with examples 2018/07/30 18:46:48 (permalink)
+1 (1)
PStechPaul
What I meant was that the mask would be shifted just one place for each iteration of the loop, whereas shifting the 32 bit ir_code variable would require a loop with LSLF or LSRF as many as 31 times to get 1UL << 31. Also, shifting a 32 bit word requires four byte-wise shifts for each operation.

OP uses a PIC18 device. For the mask method, you would need to initialize
 
    ir_code = 0x00000000; // takes 4 Tcy
    mask = 0x80000000; // takes 5 Tcy
 
and each iteration performs (worse case of 16 1's bits)
 
    ir_code |= mask; // takes 8 Tcy per 1's bit
    mask >>= 1; // takes 5 Tcy
 
for a total of (4+5)+(16*8)+(32*5) = 297 Tcy and 4 additional bytes of RAM for the mask.
 
For the ir_code shift method, there is no need to initialize ir_code because whatever in ir_code will be shifted out and replaced with new data bits, and each iteration performs
 
    ir_code >>= 1; // takes 5 Tcy
    ir_code |= (1UL << 31); // takes 1 Tcy per 1's bit
 
for a total of (32*5)+(16*1) = 176 Tcy and no additional RAM usage.
 
 
Parsing the received bit stream into four bytes would require only a single LSLF or LSRF operation for each iteration, and will result in the four bytes of address and data. That would also only require an 8 bit mask.

With the four individual bytes, the mask method takes
 
    ir_byte = 0x00; // takes 1 Tcy
    mask = 0x80; // takes 2 Tcy
 
and each iteration performs (worse case of four 1's bits per byte)
 
    ir_byte |= mask; // takes 2 Tcy per 1's bit
    mask >>= 1; // takes 2 Tcy
 
for a total of (1+2)+(4*2)+(8*2) = 27 Tcy per byte with four 1's bit, or (4*27) = 108 Tcy for four bytes.
 
The ir_byte shift method takes
 
    ir_byte >>= 1; // takes 2 Tcy
    ir_byte |= 0x80; // takes 1 Tcy per 1's bit
 
for a total of (8*2)+(4*1) = 20 Tcy per byte with four 1's bit, or (4*20) = 80 Tcy for four bytes.
 
However, this method may take more program memory; indirect addressing with pointer might reduce it.
 

You could also just conditionally OR the ir_code variable with 0x800000 when a "1" is detected, and shift right once for each operation.

That is what my code in Post #242 is doing.
 
Page: << < ..111213 Showing page 13 of 13
Jump to:
© 2019 APG vNext Commercial Version 4.5