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 ... 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
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") 
PrinceNai



Joined: 31 Oct 2016
Posts: 527
Location: Montenegro

View user's profile Send private message

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

It can't, that is where this bit is located on 18f46k22. I wrote in one of the previous posts that you'll have to find that bit for your PIC. Yours is in the OPTION_REG, bit 6. Page 176 of datasheet.

So: #bit INTDEG = getenv("BIT:OPTION_REG.INTEDG")

I just noticed there is a typo in my program here (should be #bit INTEDG). Use this the way it is written here.
temtronic



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

View user's profile Send private message

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

CURIOUS... I see ICD=TRUE....

Is there a possibility that that can cause problems ? I've never used it but know that building in 'debug' and trying to run in the Real World doesn't work.
PrinceNai



Joined: 31 Oct 2016
Posts: 527
Location: Montenegro

View user's profile Send private message

PostPosted: Sun Feb 09, 2025 1:07 pm     Reply with quote

Never had a problem or noticed any difference so far. I also never checked if the .hex is different with that option enabled. Did a quick build with it turned off now and the .hex size stays the same.
In this particular case the receiving PIC is in debug mode for testing purposes.
bulut_01



Joined: 24 Feb 2024
Posts: 206

View user's profile Send private message

PostPosted: Sun Feb 09, 2025 2:47 pm     Reply with quote

PrinceNai wrote:
Never had a problem or noticed any difference so far. I also never checked if the .hex is different with that option enabled. Did a quick build with it turned off now and the .hex size stays the same.
In this particular case the receiving PIC is in debug mode for testing purposes.


What hardware do you use to debug? Pickit 3 or icd3
PrinceNai



Joined: 31 Oct 2016
Posts: 527
Location: Montenegro

View user's profile Send private message

PostPosted: Sun Feb 09, 2025 3:10 pm     Reply with quote

Pickit3.

Below is the comparison between two streams you sent, 44 and 55. Green portions were the same for both.

https://ibb.co/B2MpDfh0
bulut_01



Joined: 24 Feb 2024
Posts: 206

View user's profile Send private message

PostPosted: Wed Feb 12, 2025 6:08 am     Reply with quote

PrinceNai wrote:
Pickit3.

Below is the comparison between two streams you sent, 44 and 55. Green portions were the same for both.

https://ibb.co/B2MpDfh0


Your code is not working. The reason is that all timers in 16f1824 are not overflowed by 1 us. When I debug, timer0 is overflowed by 32 us. You need to edit your code according to the timer overflow of 32 us.
temtronic



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

View user's profile Send private message

PostPosted: Wed Feb 12, 2025 6:57 am     Reply with quote

Please post your latest code
bulut_01



Joined: 24 Feb 2024
Posts: 206

View user's profile Send private message

PostPosted: Wed Feb 12, 2025 7:08 am     Reply with quote

temtronic wrote:
Please post your latest code


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: Wed Feb 12, 2025 7:47 am     Reply with quote

Code:
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);

will not produce 1us Timer0 step with 32MHz clock. Check Timer0 setup in my code.
temtronic



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

View user's profile Send private message

PostPosted: Wed Feb 12, 2025 8:03 am     Reply with quote

clock is 32Mhz
input to Timer0 is Fosc/4, so 32/4 = 8Mhz
Timer0 prescaler is '1' , so /2 = 4Mhz

1/4,000,000 = .00000025

not to sure how you calculate 32 useconds


Last edited by temtronic on Wed Feb 12, 2025 8:06 am; edited 1 time in total
bulut_01



Joined: 24 Feb 2024
Posts: 206

View user's profile Send private message

PostPosted: Wed Feb 12, 2025 8:06 am     Reply with quote

PrinceNai wrote:
Code:
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);

will not produce 1us Timer0 step with 32MHz clock. Check Timer0 setup in my code.


Your code is exactly the same, where do I check?
bulut_01



Joined: 24 Feb 2024
Posts: 206

View user's profile Send private message

PostPosted: Wed Feb 12, 2025 8:09 am     Reply with quote

PrinceNai wrote:
Code:
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);

will not produce 1us Timer0 step with 32MHz clock. Check Timer0 setup in my code.


16f1824 timer0 is 8 bit. you need 16 bit counter timer1 is 16 bit. 1 us overfloaw does not work
temtronic



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

View user's profile Send private message

PostPosted: Wed Feb 12, 2025 8:15 am     Reply with quote

so you have to change to another timer !!!
you have timers 1, 2 4, 6 on the t PIC with 16 bit counters....
PrinceNai



Joined: 31 Oct 2016
Posts: 527
Location: Montenegro

View user's profile Send private message

PostPosted: Wed Feb 12, 2025 8:16 am     Reply with quote

Then use Timer1. Change all references from Timer0 to Timer1. Mind you, overflow isn't 1us. Timer increments by 1 in 1us. Overflow is 65ms
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 ... 16, 17, 18, 19, 20  Next
Page 17 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