CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

manchester decode
Goto page Previous  1, 2, 3 ... 15, 16, 17, 18, 19, 20  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
temtronic



Joined: 01 Jul 2010
Posts: 9425
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Feb 08, 2025 11:06 am     Reply with quote

If we knew the make/model of the receiver we could search the web to see how others have done it. Also see where to pick off the correct data.
It would be nice to see at least 2 'data streams after same key pressed'.
bulut_01



Joined: 24 Feb 2024
Posts: 206

View user's profile Send private message

PostPosted: Sat Feb 08, 2025 2:04 pm     Reply with quote

PrinceNai wrote:
You always say: the code doesn't work. Maybe I didn't read all the posts carefully enough, but I don't see exactly WHAT doesn't work. I'm sure the code I posted "works". I know it because what I send from one PIC shows in the buffer of the other PIC. I'm also quite sure the other code from Mr. T works. So, what doesn't work? How do you know it doesn't? If you are relying on your logic analyzer to compare the results, you'll never ever going to see the same thing. Look at the pictures you sent. Where the analyzer "sees" the data? On one of the pictures it ignores at least one byte at the end. If you have an extra PIC, do yourself a favor. Build a transmitter that will send known data every time. Than you can compare sent with received and see if there is a difference and where. Once again, I'm 99,99999% sure the first data bit starts one TE after the 4.800us preamble. I concluded that from the shape of the signals on your pictures. There are 113 bits sent out. Count them from the last one back on the picture that has a logic 1 as the last bit. Also from the shape of the signal. If you start with the first zero after the preamble, you have 0,0,1,1,0,0,1,1. That is NOT Manchester coded data. Your analyzer takes the falling edge of the preamble as the first bit. But to cut it short. What doesn't work?


@princenai

There is a reason why I say it doesn't work, I have a remote control in my hand and I test it and I see that it doesn't work. You can't know if you have a remote control or not because you don't have the real circuit. If it worked, I wouldn't have to bother with it anyway.
note 56 bit

I understand that the code is not working, after sending data to the remote control, I try Manchester decode and when I read the buffer in the codes I see 0, I understand that the incoming data is not decoded.


Last edited by bulut_01 on Sat Feb 08, 2025 2:11 pm; edited 2 times in total
bulut_01



Joined: 24 Feb 2024
Posts: 206

View user's profile Send private message

PostPosted: Sat Feb 08, 2025 2:06 pm     Reply with quote

temtronic wrote:
If we knew the make/model of the receiver we could search the web to see how others have done it. Also see where to pick off the correct data.
It would be nice to see at least 2 'data streams after same key pressed'.


mr. temtronic The receiver circuit is my own design, there is no brand.
PrinceNai



Joined: 31 Oct 2016
Posts: 527
Location: Montenegro

View user's profile Send private message

PostPosted: Sat Feb 08, 2025 3:45 pm     Reply with quote

Quote:

note 56 bit

112 bits of useful data come in. 56 1-0 or 0-1 pairs which translate to 56 bits when decoded.

Quote:

You can't know if you have a remote control or not because you don't have the real circuit.

I actually do. Not your remote, of course, but a real, hardware board that mimics the data and the timings from one of the pictures you posted. And a real board on the other side that receives and decodes that data. Connected to a Pickit3 where I can see the contents of the reception buffer. And verify if the state machine reaches the transition points as expected. And a logic analyzer where I can confirm that the data I coded leaves the transmitting board and has the correct pattern.


Quote:

when I read the buffer in the codes I see 0


This is an information. What is actually happening. So, can you confirm that you correctly sense a 4800us impulse that signifies the beginning of the data? If you are not using a debugger, maybe turn on a LED when that is correctly received. You need to eliminate things one by one. Preamble received? Yes, so the problem isn't here. No, wrong timing, interrupts not firing,...
temtronic



Joined: 01 Jul 2010
Posts: 9425
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Feb 08, 2025 3:47 pm     Reply with quote

OK, what make /model is the transmitter ?
or post 2 complete 'button presses' of the TRANSMITTERS data not from your 'receiver' circuit.
bulut_01



Joined: 24 Feb 2024
Posts: 206

View user's profile Send private message

PostPosted: Sat Feb 08, 2025 4:03 pm     Reply with quote

temtronic wrote:
OK, what make /model is the transmitter ?
or post 2 complete 'button presses' of the TRANSMITTERS data not from your 'receiver' circuit.

okey same key 2 different data


Last edited by bulut_01 on Mon Feb 24, 2025 1:43 pm; edited 1 time in total
PrinceNai



Joined: 31 Oct 2016
Posts: 527
Location: Montenegro

View user's profile Send private message

PostPosted: Sat Feb 08, 2025 5:58 pm     Reply with quote

This is how the data copied from your picture 55 looks in Excel:

https://ibb.co/gZ5PpGsd

Note the blue row.

My fake transmitter is coded to transmit this sequence of bits. 640us Te, 5 times 4xTe long sync bytes and 7xTe long preamble. Leading zero of Te and 112 bits of data.

This is the result I get in my receiving PIC:

https://ibb.co/99RGr1BD

Look at DecodedInputData
temtronic



Joined: 01 Jul 2010
Posts: 9425
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Feb 08, 2025 9:11 pm     Reply with quote

Pressing the same key should produce the same data,otherwise the receiver can't control whatever it's supposed to.
Since PN's code works, according to the eXcell-ent analysis, there has to be something odd about the transmitter,

Sadly we don't have any real good information about the device, IE the actual formatting of the data stream.
PrinceNai



Joined: 31 Oct 2016
Posts: 527
Location: Montenegro

View user's profile Send private message

PostPosted: Sun Feb 09, 2025 4:52 am     Reply with quote

Yes, getting the bits over is the easy part. What to do with them once they are there is the question :-).

Here I have no idea if the receiving hardware of the OP even works. I know it is powered on, of course. Is the receiving PIC seeing the data, entering the interrupts? Can it turn on a LED if any kind of transmission is detected? Easy stuff, when a transition is detected, toggle a LED. So when the button is pressed, something blinks on the other side. Maybe a follower, when a signal is detected, set another pin to the same level and hook the analyzer on the input and the output pin. Interrupt on change, when it fires, sample the input and set the output accordingly. 5 lines of code. The pattern should be the same on both channels. How is the debugging done, any kind of output to check what the code is doing? I saw that PickitPlus software is used, but that is a programming software only, not a debugger.
bulut_01



Joined: 24 Feb 2024
Posts: 206

View user's profile Send private message

PostPosted: Sun Feb 09, 2025 5:41 am     Reply with quote

PrinceNai wrote:
Yes, getting the bits over is the easy part. What to do with them once they are there is the question :-).

Here I have no idea if the receiving hardware of the OP even works. I know it is powered on, of course. Is the receiving PIC seeing the data, entering the interrupts? Can it turn on a LED if any kind of transmission is detected? Easy stuff, when a transition is detected, toggle a LED. So when the button is pressed, something blinks on the other side. Maybe a follower, when a signal is detected, set another pin to the same level and hook the analyzer on the input and the output pin. Interrupt on change, when it fires, sample the input and set the output accordingly. 5 lines of code. The pattern should be the same on both channels. How is the debugging done, any kind of output to check what the code is doing? I saw that PickitPlus software is used, but that is a programming software only, not a debugger.


interrupts rda timer ex_ınt everything is working fully, you must have thought we were amateurs, manch algorithm is not working, I just have circuit design work to finish, I will deal with the published codes
PrinceNai



Joined: 31 Oct 2016
Posts: 527
Location: Montenegro

View user's profile Send private message

PostPosted: Sun Feb 09, 2025 6:20 am     Reply with quote

Quote:
you must have thought we were amateurs


No, I don't :-). But since you are a bit on the stiff side with the information, I must ask. Must is a bit strong word, at this point I simply want to, because it really interests me. You mentioned all zeroes in the buffer. Fine. Does your code ever reach the point where it must write a one there? Does it increment counters, at least two of them? How can I know that without asking you? I have no idea about the equipment you use, save for the analyzer and the programming software. What are you debugging with? How? You never say: I did this, I tried that. Result is this. I know that my setup works. And it didn't work off the bat, far from it. But I went step by step. There is a diode blinking, so I know my PIC is alive. There was a breakpoint sitting in the first two states so I knew I could catch the preamble every time. Only after that I went to the decoding part. Drew a diagram of one byte and worked out the timings. Catching my own errors, both in code and in mental process. I prove to myself every time that the code does what you write, not what you think it should do. Those two things are seldom the same at the start.

Anyway, I was tinkering with the code since the version posted previously, so this is the last version:

Receiving part:
Code:

#include <18F46K22.h>
#device ADC=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOPUT

#device ICD=TRUE
#use delay(internal = 32000000)

/////////////////////////// DEFINES /////////////////////////////////
#define NUMBER_OF_BYTES 7                                            // number of DECODED bytes to receive
#define TE 640                                                       // duration of one bit in us, change as needed
#define PREAMBLE_MAX_TIME 8*TE
#define PREAMBLE_MIN_TIME 6*TE                                       // we expect a 7 bit preamble, make some room for clock error
#define TRANSITION_MIN_TIME 1.5*TE                                   // same here when sampling
#define TRANSITION_MAX_TIME 2.5*TE

////////////////////////// VARIABLES ////////////////////////////////

char DecodedInputData[10];                                           // buffer for decoded data
char CurrentByte = 0;

int8 InputByteCounter = 0;                                           // keeps track about which byte we are filling in
int8 BitPosition = 0;                                                // bit position of the incoming data
int8 Have_Data = 0;                                                  // flag to inform main data was received and decoded
                                                       
// switch
enum {GotRisingEdge = 1, GotFallingEdge, SampleData};                // state machine switch
int8 DecodeSwitch = GotRisingEdge;
// Timer
int16 TimerValue;
int8 TMR0_Overflow = 0;                                              // how many times TMR0 has overflowed


////////////////////////// FUNCTIONS ////////////////////////////////

#bit INTDEG  = getenv("BIT:INTCON2.INTEDG0")                         // declare edge selection bit for INT_EXT. INTDEG is a generic name (some PIC's have more than one of those registers,
void ToggleIntEdge (void){                                           // 18f46k22 has INTDEG0, for example) for external interrupt on Pin_B0. Change this for the PIC you use
   if(INTDEG == 1){                                                  // check which edge is currently selected
      INTDEG = 0;                                                    // activate interrupt on falling edge
   }
   else{
      INTDEG = 1;                                                    // activate interrupt on rising edge
   }
}

// ------------------------------------------------------------------
void ClearBuffer (void){
   DecodedInputData[0] = 0x00;                                       // lazy :-)
   DecodedInputData[1] = 0x00;
   DecodedInputData[2] = 0x00;
   DecodedInputData[3] = 0x00;                                       // lazy :-)
   DecodedInputData[4] = 0x00;
   DecodedInputData[5] = 0x00;
   DecodedInputData[6] = 0x00;
   DecodedInputData[7] = 0x00;
   DecodedInputData[8] = 0x00;
   DecodedInputData[9] = 0x00;
}


//////////////////////// END OF  FUNCTIONS //////////////////////////

// ******************************************************************
//                        INTERRUPTS
// ******************************************************************

#INT_TIMER0
void  TIMER0_isr(void)
{
   TMR0_Overflow++;                                                  // count timer TMR0_Overflows
}

// ------------------------------------------------------------------
#INT_EXT
void  EXT_isr(void)
{
   clear_interrupt(INT_EXT);                                         // clear interrupt, needed for this particular interrupt type or you come back straight away
   
//default handling, check if switch variable is out of usefull bounds           
   if (DecodeSwitch < 1 || DecodeSwitch > 3)
   {           
//      printf("Default handling, testval is out of bounds, DecodeSwitch == %u\r\n", DecodeSwitch);
      continue;                                                      // Miss switch. The continue statement causes the next iteration of the enclosing loop(While, For, Do) to begin.
   }
// ******************************************************************
// ******************************************************************           
   switch (DecodeSwitch)                                             // state machine used to receive and decode Mancester encoded data
   {
// ------------------------------------------------------------------
// wait for a rising edge on the input, this state also serves as a reset. Always come here with L_TO_H transition set (maybe not even needed)!

      case GotRisingEdge:                                            // we have a rising edge, could be start of the preamble
      {           
         set_timer0(0);                                              // reset timer
         TMR0_Overflow = 0;                                          // and various counters
         BitPosition = 0;
         InputByteCounter = 0;                                           
         CurrentByte = 0;
         Have_Data = 0;                                              // and flags         
         ext_int_edge(0, H_TO_L);                                    // change direction of the interrupt to falling edge
         DecodeSwitch = GotFallingEdge;                              // and go to GotFallingEdge to see if we have a preamble         
         break;
      }           
     
// ------------------------------------------------------------------             
      case GotFallingEdge:                                           // we have a falling edge, pulse ended. Might be preamble.
      {
         ext_int_edge(0, L_TO_H);                                    // prepare next interrupt on a rising edge     
         TimerValue = get_timer0();                                  // check the time that elapsed between two interrupts
         
         if(TMR0_Overflow == 0 && TimerValue > PREAMBLE_MIN_TIME && TimerValue < PREAMBLE_MAX_TIME) {   // bingo, time is good, we have a preamble
            set_timer0(0);                                           // preset timer for next measurement
            TMR0_Overflow = 0;
            DecodeSwitch = SampleData;                               // and go sample the input         
         }         
         else{                                                       // not good, pulse was either too short or too long for a preamble.                                   
            DecodeSwitch = GotRisingEdge;                            // Reset state machine
         }                 
         break;
      }
// ------------------------------------------------------------------
// We are looking for a transition that in Mancester coding always exist in the middle of a symbol,
// so the sampling is done every 2TE. That can be on the first or second following interrupt,
// depending on whether two subsequent symbols have the same or different value.
// We are using TMR0 value to find if it is time to sample. If it is, sample the input and store
// to the correct location in the data buffer.
// The word symbol means a 2-bit pair that represents either a 1 or a 0.

      case SampleData:
      {
         ToggleIntEdge();                                            // change the active edge of the interrupt for the next one,
                                                                     // because transition can be either 0-1 or 1-0, but hardly
                                                                     // 0-0 or 1-1
         TimerValue = get_timer0();
// If this interrupt occured in a time frame from 0,5*TE to 1,5*TE, this symbol has the same
// value as the previous, meanng that interrupt occured also at the start of the symbol, not only in the middle.
// So we need to wait for the next interrupt that will come at the middle of a symbol to actually sample data
                                                                           
// Time between two edges is correct, read input state. This test is intentionally put in the first place
// so it gets serviced first, since the timer is already running for the next symbol

         if(TMR0_Overflow == 0 && TimerValue >= TRANSITION_MIN_TIME && TimerValue <= TRANSITION_MAX_TIME){  // this is the one we are looking for, sample and store the data
            set_timer0(0);                                           // reset timer for the next symbol

// INVERT THE DECODING LOGIC AS NEEDED HERE!!!!! COMMENT THE WRONG IF OUT!!!! LIKE THIS WORKS FOR IEEE 802 CODING, 01 IS 1, 10 IS 0   
       
//            if(input_state(pin_B0) == 0){
            if(input_state(pin_B0) == 1){
               bit_set(CurrentByte, 7 - BitPosition);                // Sample input. Set appropriate bit if needed, leave 0 otherwise               
               }                                                     //
            BitPosition++;
            if(BitPosition > 7){                                     // one byte of data was received
               BitPosition = 0;
               DecodedInputData[InputByteCounter] = CurrentByte;     // store that data into the buffer
               CurrentByte = 0;                                      // prepare variable for next byte (all zeroes, since we are only setting the bits needed)
               InputByteCounter++;                                   // increment byte counter for a correct position in the buffer
               
               if (InputByteCounter == NUMBER_OF_BYTES){             // if all the bytes are in the buffer, reception is done
                  ext_int_edge(0, L_TO_H);
                  Have_Data = 1;                                     // we have data, signal that to main
                  DecodeSwitch = GotRisingEdge;                      // and reset state machine for the next reception
               }  // if byte counter
            }     // if bit position 
         
         }        // end sampling                                                                     
                                                                                                                                                                                                           
// time between two edges is too short for sampling, it may be transition between two symbols with the same value                                                                   
         else if(TMR0_Overflow == 0 && TimerValue < TRANSITION_MIN_TIME){      // the transition came too soon for sampling, exit interrupt but leave
            delay_cycles(1);                                         // the timer running and stay in the same case
         }
         
// time between two edges to long for a valid symbol, reset         
         else{                                                       // time between two transitions was too long,
            ext_int_edge(0, L_TO_H);
            DecodeSwitch = GotRisingEdge;                            // reset state machine
         }
         break;
      }           // end case
   }              // end switch
}                 // end interrupt

// ******************************************************************
//                       END OF INTERRUPTS
// ******************************************************************

void main()
{
   ClearBuffer();                                                    // clear receiving buffer
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);                          // 65.535us, resolution 1us. RESOLUTION MUST BE 1us!!!!
     
   clear_interrupt(INT_EXT);   
   ext_int_edge(0,L_TO_H);
   enable_interrupts(INT_EXT);
     
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   
   while(TRUE)
   {

      if(Have_Data == 1){
         Have_Data = 0;                                              // do something with data
     
      }

   }

}


and the code used to send the data out, full 14 bytes, copied from the picture:
Code:

#include <18F46K22.h>
#device ADC=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOPUT

//#device ICD=TRUE
#use delay(internal=32000000)
#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3,force_hw)

// ******************************************************************
int8 k;
// buttons
#define MODE_switch PIN_B1
int8 active_state_MODE;
int8 previuos_state_MODE; 
int8 MODE_switch_is_pressed = FALSE;
#define Te 640
#define Transmit_Pin PIN_B5

////////////////////////// FUNCTIONS ////////////////////////////////
// ------------------------------------------------------------------
void i (void){
// 1
   output_high(Transmit_Pin);
   delay_us(Te);
   output_low(Transmit_Pin);
   delay_us(Te);
}
// ------------------------------------------------------------------

void o (void){
// 0
   output_low(Transmit_Pin);
   delay_us(Te);
   output_high(Transmit_Pin);
   delay_us(Te);
}
// ------------------------------------------------------------------

void ReadModeButton(void){
// detect ModeButton, presumes 0 is read if the ModeButton is pressed.Debouncing part.
   active_state_MODE = input_state(MODE_switch);                     // Read the button             
   if((previuos_state_MODE == 1) && (active_state_MODE == 0)){                       
      MODE_switch_is_pressed = TRUE;                                 // switch pressed, raise "MODE PRESSED" flag
   }                                                                 // must be cleared in software   
   previuos_state_MODE = active_state_MODE;                          // Save current value for next time
}
// ------------------------------------------------------------------
// bit 6 controls the active edge for INT_EXT
#bit INTDEG  = getenv("BIT:INTCON2.INTEDG0")                         // declare edge selection bit for INT_EXT. INTDEG is a generic name (some PIC's have more than one of those registers,
void ToggleIntEdge (void){                                           // 18f46k22 has INTDEG0, for example) for external interrupt on Pin_B0. Change this for the PIC you use
   if(INTDEG == 1){
      INTDEG = 0;                                                    // check which edge is currently selected
   }
   else{
      INTDEG = 1;                                                    // and change to the oposite edge
   }
}

// ******************************************************************

#INT_TIMER0
void  TIMER0_isr(void)
{
   ReadModeButton();
}

// ------------------------------------------------------------------

void main()
{
   output_low(Transmit_Pin);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);                          // 125ns cycle, 8 ms overflow
   enable_interrupts(INT_TIMER0);                                    // timer0 takes care of buttons and timings
   enable_interrupts(GLOBAL); 

   while(TRUE)
   {
   
//////
      if(MODE_switch_is_pressed == TRUE){
         MODE_switch_is_pressed = FALSE;
         disable_interrupts(INT_TIMER0);                             // prevent button presses while sending


         ToggleIntEdge();
      // wait -------------------------------------------------------------
         output_low(Transmit_Pin);
         delay_ms(2000);
           
      // sync -------------------------------------------------------------
         for(k= 0; k < 5; k++){
            output_high(Transmit_Pin);
            delay_us(4*Te);
            output_low(Transmit_Pin);
            delay_us(4*Te);
         }
         
      // preamble ---------------------------------------------------------
         output_high(Transmit_Pin);
         delay_us(7*Te);
         output_low(Transmit_Pin);
         
      // leading 0
         delay_us(Te);
     
      // data -------------------------------------------------------------
     
      // byte1 ----------
      // 0
         o();
      // 1
         i();     
      // 0
         o();
      // 1
         i();
         
      // byte2 ----------
      // 1
         i(); 
      // 0
         o();
      // 1
         i();
      // 0
         o();
         
      // byte3 ---------
      // 0
         o();
      // 1
         i();   
      // 1
         i();
      // 1
         i();
         
      // byte4 ---------
      // 0
         o();     
      // 0
         o();
      // 0
         o();     
      // 0
         o();
         
      // byte5 ----------
      // 0
         o();
      // 0
         o();
      // 0
         o();
      // 0
         o();
         
      // byte6 ----------
      // 1
         i();
      // 1
         i();
      // 1
         i();
      // 0
         o();
         
      // byte7 ----------
      // 1
         i();
      // 1
         i();
      // 1
         i();
      // 1
         i();
         
      // byte8 ----------
      // 1
         i();
      // 0
         o();
      // 1
         i();
      // 0
         o();
         
      // byte9 ----------
      // 0
         o();
      // 1
         i();
      // 1
         i();
      // 0
         o();
         
      // byte10 ----------
      // 1
         i();
      // 0
         o();
      // 0
         o();
       // 1
         i();
         
      // byte11 ----------
      // 1
         i();
      // 0
         o();
      // 0
         o();
       // 1
         i();
         
      // byte12 ----------
      // 1
         i();
      // 0
         o();
      // 0
         o();
       // 1
         i();
         
      // byte13 ----------
      // 1
         i();
      // 0
         o();
      // 1
         i();
       // 0
         o();         
         
      // byte14 ----------
      // 1
         i();
      // 0
         o();
      // 1
         i();
       // 0
         o();
         
      // pause ------------------------------------------------------------
         output_low(Transmit_Pin);
         delay_ms(500);
         enable_interrupts(INT_TIMER0);
   
      }
   
//////////////////
   }

}

temtronic



Joined: 01 Jul 2010
Posts: 9425
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Feb 09, 2025 10:49 am     Reply with quote

hmm, just thinking, it'd be kind of funny if the received data bits are actually inverted from the transmitted ones..... Sad
PrinceNai



Joined: 31 Oct 2016
Posts: 527
Location: Montenegro

View user's profile Send private message

PostPosted: Sun Feb 09, 2025 11:19 am     Reply with quote

What exactly do you mean by "inverted"? Inverted Manchester logic (that is taken care of in the code, comment/un-comment one line) or sent out LSB first? Last two pictures sure do look very similar at the end. It shouldn't be too hard to rearrange 56 bits so that the last one comes on the first place and so on. And of course type in the pattern also for the other picture, I only did one.
temtronic



Joined: 01 Jul 2010
Posts: 9425
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Feb 09, 2025 11:33 am     Reply with quote

I saw that there's 2 versions of Manchester...yeesh, so much for 'standards'......
Haven't seen a proper breakdown of the data ,least not that I can recall so wondering why 2 keypresses aren't the same.
I still have 20cm of snow to deal with, ugh......so my breaktime is over.
bulut_01



Joined: 24 Feb 2024
Posts: 206

View user's profile Send private message

PostPosted: Sun Feb 09, 2025 12:01 pm     Reply with quote

PrinceNai wrote:
Quote:
you must have thought we were amateurs


No, I don't :-). But since you are a bit on the stiff side with the information, I must ask. Must is a bit strong word, at this point I simply want to, because it really interests me. You mentioned all zeroes in the buffer. Fine. Does your code ever reach the point where it must write a one there? Does it increment counters, at least two of them? How can I know that without asking you? I have no idea about the equipment you use, save for the analyzer and the programming software. What are you debugging with? How? You never say: I did this, I tried that. Result is this. I know that my setup works. And it didn't work off the bat, far from it. But I went step by step. There is a diode blinking, so I know my PIC is alive. There was a breakpoint sitting in the first two states so I knew I could catch the preamble every time. Only after that I went to the decoding part. Drew a diagram of one byte and worked out the timings. Catching my own errors, both in code and in mental process. I prove to myself every time that the code does what you write, not what you think it should do. Those two things are seldom the same at the start.

Anyway, I was tinkering with the code since the version posted previously, so this is the last version:

Receiving part:
Code:

#include <18F46K22.h>
#device ADC=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOPUT

#device ICD=TRUE
#use delay(internal = 32000000)

/////////////////////////// DEFINES /////////////////////////////////
#define NUMBER_OF_BYTES 7                                            // number of DECODED bytes to receive
#define TE 640                                                       // duration of one bit in us, change as needed
#define PREAMBLE_MAX_TIME 8*TE
#define PREAMBLE_MIN_TIME 6*TE                                       // we expect a 7 bit preamble, make some room for clock error
#define TRANSITION_MIN_TIME 1.5*TE                                   // same here when sampling
#define TRANSITION_MAX_TIME 2.5*TE

////////////////////////// VARIABLES ////////////////////////////////

char DecodedInputData[10];                                           // buffer for decoded data
char CurrentByte = 0;

int8 InputByteCounter = 0;                                           // keeps track about which byte we are filling in
int8 BitPosition = 0;                                                // bit position of the incoming data
int8 Have_Data = 0;                                                  // flag to inform main data was received and decoded
                                                       
// switch
enum {GotRisingEdge = 1, GotFallingEdge, SampleData};                // state machine switch
int8 DecodeSwitch = GotRisingEdge;
// Timer
int16 TimerValue;
int8 TMR0_Overflow = 0;                                              // how many times TMR0 has overflowed


////////////////////////// FUNCTIONS ////////////////////////////////

#bit INTDEG  = getenv("BIT:INTCON2.INTEDG0")                         // declare edge selection bit for INT_EXT. INTDEG is a generic name (some PIC's have more than one of those registers,
void ToggleIntEdge (void){                                           // 18f46k22 has INTDEG0, for example) for external interrupt on Pin_B0. Change this for the PIC you use
   if(INTDEG == 1){                                                  // check which edge is currently selected
      INTDEG = 0;                                                    // activate interrupt on falling edge
   }
   else{
      INTDEG = 1;                                                    // activate interrupt on rising edge
   }
}

// ------------------------------------------------------------------
void ClearBuffer (void){
   DecodedInputData[0] = 0x00;                                       // lazy :-)
   DecodedInputData[1] = 0x00;
   DecodedInputData[2] = 0x00;
   DecodedInputData[3] = 0x00;                                       // lazy :-)
   DecodedInputData[4] = 0x00;
   DecodedInputData[5] = 0x00;
   DecodedInputData[6] = 0x00;
   DecodedInputData[7] = 0x00;
   DecodedInputData[8] = 0x00;
   DecodedInputData[9] = 0x00;
}


//////////////////////// END OF  FUNCTIONS //////////////////////////

// ******************************************************************
//                        INTERRUPTS
// ******************************************************************

#INT_TIMER0
void  TIMER0_isr(void)
{
   TMR0_Overflow++;                                                  // count timer TMR0_Overflows
}

// ------------------------------------------------------------------
#INT_EXT
void  EXT_isr(void)
{
   clear_interrupt(INT_EXT);                                         // clear interrupt, needed for this particular interrupt type or you come back straight away
   
//default handling, check if switch variable is out of usefull bounds           
   if (DecodeSwitch < 1 || DecodeSwitch > 3)
   {           
//      printf("Default handling, testval is out of bounds, DecodeSwitch == %u\r\n", DecodeSwitch);
      continue;                                                      // Miss switch. The continue statement causes the next iteration of the enclosing loop(While, For, Do) to begin.
   }
// ******************************************************************
// ******************************************************************           
   switch (DecodeSwitch)                                             // state machine used to receive and decode Mancester encoded data
   {
// ------------------------------------------------------------------
// wait for a rising edge on the input, this state also serves as a reset. Always come here with L_TO_H transition set (maybe not even needed)!

      case GotRisingEdge:                                            // we have a rising edge, could be start of the preamble
      {           
         set_timer0(0);                                              // reset timer
         TMR0_Overflow = 0;                                          // and various counters
         BitPosition = 0;
         InputByteCounter = 0;                                           
         CurrentByte = 0;
         Have_Data = 0;                                              // and flags         
         ext_int_edge(0, H_TO_L);                                    // change direction of the interrupt to falling edge
         DecodeSwitch = GotFallingEdge;                              // and go to GotFallingEdge to see if we have a preamble         
         break;
      }           
     
// ------------------------------------------------------------------             
      case GotFallingEdge:                                           // we have a falling edge, pulse ended. Might be preamble.
      {
         ext_int_edge(0, L_TO_H);                                    // prepare next interrupt on a rising edge     
         TimerValue = get_timer0();                                  // check the time that elapsed between two interrupts
         
         if(TMR0_Overflow == 0 && TimerValue > PREAMBLE_MIN_TIME && TimerValue < PREAMBLE_MAX_TIME) {   // bingo, time is good, we have a preamble
            set_timer0(0);                                           // preset timer for next measurement
            TMR0_Overflow = 0;
            DecodeSwitch = SampleData;                               // and go sample the input         
         }         
         else{                                                       // not good, pulse was either too short or too long for a preamble.                                   
            DecodeSwitch = GotRisingEdge;                            // Reset state machine
         }                 
         break;
      }
// ------------------------------------------------------------------
// We are looking for a transition that in Mancester coding always exist in the middle of a symbol,
// so the sampling is done every 2TE. That can be on the first or second following interrupt,
// depending on whether two subsequent symbols have the same or different value.
// We are using TMR0 value to find if it is time to sample. If it is, sample the input and store
// to the correct location in the data buffer.
// The word symbol means a 2-bit pair that represents either a 1 or a 0.

      case SampleData:
      {
         ToggleIntEdge();                                            // change the active edge of the interrupt for the next one,
                                                                     // because transition can be either 0-1 or 1-0, but hardly
                                                                     // 0-0 or 1-1
         TimerValue = get_timer0();
// If this interrupt occured in a time frame from 0,5*TE to 1,5*TE, this symbol has the same
// value as the previous, meanng that interrupt occured also at the start of the symbol, not only in the middle.
// So we need to wait for the next interrupt that will come at the middle of a symbol to actually sample data
                                                                           
// Time between two edges is correct, read input state. This test is intentionally put in the first place
// so it gets serviced first, since the timer is already running for the next symbol

         if(TMR0_Overflow == 0 && TimerValue >= TRANSITION_MIN_TIME && TimerValue <= TRANSITION_MAX_TIME){  // this is the one we are looking for, sample and store the data
            set_timer0(0);                                           // reset timer for the next symbol

// INVERT THE DECODING LOGIC AS NEEDED HERE!!!!! COMMENT THE WRONG IF OUT!!!! LIKE THIS WORKS FOR IEEE 802 CODING, 01 IS 1, 10 IS 0   
       
//            if(input_state(pin_B0) == 0){
            if(input_state(pin_B0) == 1){
               bit_set(CurrentByte, 7 - BitPosition);                // Sample input. Set appropriate bit if needed, leave 0 otherwise               
               }                                                     //
            BitPosition++;
            if(BitPosition > 7){                                     // one byte of data was received
               BitPosition = 0;
               DecodedInputData[InputByteCounter] = CurrentByte;     // store that data into the buffer
               CurrentByte = 0;                                      // prepare variable for next byte (all zeroes, since we are only setting the bits needed)
               InputByteCounter++;                                   // increment byte counter for a correct position in the buffer
               
               if (InputByteCounter == NUMBER_OF_BYTES){             // if all the bytes are in the buffer, reception is done
                  ext_int_edge(0, L_TO_H);
                  Have_Data = 1;                                     // we have data, signal that to main
                  DecodeSwitch = GotRisingEdge;                      // and reset state machine for the next reception
               }  // if byte counter
            }     // if bit position 
         
         }        // end sampling                                                                     
                                                                                                                                                                                                           
// time between two edges is too short for sampling, it may be transition between two symbols with the same value                                                                   
         else if(TMR0_Overflow == 0 && TimerValue < TRANSITION_MIN_TIME){      // the transition came too soon for sampling, exit interrupt but leave
            delay_cycles(1);                                         // the timer running and stay in the same case
         }
         
// time between two edges to long for a valid symbol, reset         
         else{                                                       // time between two transitions was too long,
            ext_int_edge(0, L_TO_H);
            DecodeSwitch = GotRisingEdge;                            // reset state machine
         }
         break;
      }           // end case
   }              // end switch
}                 // end interrupt

// ******************************************************************
//                       END OF INTERRUPTS
// ******************************************************************

void main()
{
   ClearBuffer();                                                    // clear receiving buffer
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);                          // 65.535us, resolution 1us. RESOLUTION MUST BE 1us!!!!
     
   clear_interrupt(INT_EXT);   
   ext_int_edge(0,L_TO_H);
   enable_interrupts(INT_EXT);
     
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   
   while(TRUE)
   {

      if(Have_Data == 1){
         Have_Data = 0;                                              // do something with data
     
      }

   }

}





16F1824 register not
Code:
#bit INTDEG  = getenv("BIT:INTCON2.INTEDG0") 
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3 ... 15, 16, 17, 18, 19, 20  Next
Page 16 of 20

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group