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 ... 13, 14, 15 ... 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: 213

View user's profile Send private message

PostPosted: Tue Feb 04, 2025 7:12 pm     Reply with quote

temtronic wrote:
find them again, maybe they have the receive code as well !


Unfortunately, I can't reach anyone from the old offline block, I have to solve this myself.
gaugeguy



Joined: 05 Apr 2011
Posts: 319

View user's profile Send private message

PostPosted: Wed Feb 05, 2025 7:18 am     Reply with quote

bulut_01,
Where did you get your repeated references to UART and KEELOQ from?
temtronic



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

View user's profile Send private message

PostPosted: Wed Feb 05, 2025 7:20 am     Reply with quote

this line of code ...

delayMicroseconds(SYMBOL);

looks like Arudino C ??

If so a proper search might find it.
bulut_01



Joined: 24 Feb 2024
Posts: 213

View user's profile Send private message

PostPosted: Wed Feb 05, 2025 7:32 am     Reply with quote

temtronic wrote:
this line of code ...

delayMicroseconds(SYMBOL);

looks like Arudino C ??

If so a proper search might find it.


yes arudio I need an algorithm to solve this
temtronic



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

View user's profile Send private message

PostPosted: Wed Feb 05, 2025 7:36 am     Reply with quote

OK, go to some Ardunio forum ! Whoever wrote the transmitter code MUST have written a receiver code. Google returns 100s of hits for 'ardunio manchester' so if you have the authors name add that to reduce the number of hits.
temtronic



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

View user's profile Send private message

PostPosted: Wed Feb 05, 2025 8:14 am     Reply with quote

where ?
from his 3rd post...
mcu 16f1824 rf module 433 mhz reading data receiving 10 byte data frame sending remote control keeloq manchester 1500 baund communication speed.
ccs c last version
....
hence the trips down various 'forks in the roads'.

It turns out it's for an RF device that has SOME of the data encoded in one of the Manchester formats.
bulut_01



Joined: 24 Feb 2024
Posts: 213

View user's profile Send private message

PostPosted: Wed Feb 05, 2025 8:21 am     Reply with quote

mr. temtronic What you said doesn't help me, actually my request is that there is a very simple sending algorithm and to solve it, create a decode algorithm. The answer to my question is very simple.
Ttelmah



Joined: 11 Mar 2010
Posts: 19739

View user's profile Send private message

PostPosted: Wed Feb 05, 2025 8:38 am     Reply with quote

The point is this is not a 'write it for you' forum, but one to help you to
write your own code.
This won't be right, but should be close:
Code:

#include <16F1824.h>                                                                 
#device ADC = 8                                                   
#FUSES NOWDT                                             
#fuses PUT                                               
#FUSES NOMCLR
#FUSES NOLVP
#FUSES STVREN
#FUSES NOIESO
#FUSES NOFCMEN
#FUSES NOWRT
#FUSES NODEBUG
#use delay(internal = 16M)

//Decoder for stream with header bytes followed by Mancester data
//The sequence of the data is signal starts low. Then 7 pulses of about 5mSec
//high/low, followed by the signal ending high and holding for 7.5mSec.
//Then a falling edge which marks the start clock edge of the data.
//Decoding ffrom here is standard Manchester, with 1/0 depending on whether
//the clock edges are in sync or out of sunc with the bit rate. Basic
//Manchester clock rate is about 400bps. So transitions are at twice this
//rate. 800Hz.
//Use INT_IOC to detect the edges, and Timer4 for timing. Want a sensible count
//per half bitm so run Timer4 off Fosc/16. 16MHz clock should give about 5000
//for the initial clocks, and 1250 for the individual edges.
//

enum states {HEADER, SYNC, DATA};
enum states state=Header;

#define CHANGE 1500 //Value below which to see as a half clock so phase change
#define SYNCPULSE 4800 //Value above which to see sync.
int8 rdat[10]; //data array to take the received bytes
int1 flag=0; //flag to trigger search for sync bytes.
int1 have_data=FALSE;

#INT_IOC
void edge(void)
{  //Edge detector
   static int16 last=0;
   static int16 delta, val;
   static int8 ctr=0;
   static int8 bit=128;
   static int1 clock=0;
   static int1 alternate=0;
   int8 dummy;
   dummy=input(PIN_A0); //read pin
   clear_interrupt(INT_IOC_A0);
   if (flag==0) //Start timing again
   {
      last=get_timer1(); //record first edge time
      flag=1;
      return;
   }
   val=get_timer1(); //get the current timer value
   delta=val-last; //Now have delta from last edge
   last=val; //and store for next time
   switch (state) {
   case HEADER:
      //We keep retesting till the time exceeds SYNCPULSE time
      if (delta>SYNCPULSE)
         state++;
      break;   
   case SYNC:
      //get here we have seen a pulse over 6000 counts
      //Next edge is the drop to matk the start of the data.
      state++;
      break;
   case DATA:
      //Now we are clocking in data. If the time is over 1500 clocks then we
      //have a change otherwise we are in sync.
      if(delta>CHANGE)
      {  //Here we are in sync with the master bit clock
         if (clock)
            rdat[ctr]|=bit;
         else
            rdat[ctr]&=(bit^0xFF);
         clock=!clock;         
      }
      else
      {
         //here out of sync
         if (clock)
            rdat[ctr]&=(bit^0xFF);
         else
            rdat[ctr]|=bit;         
         if (alternate)
            clock=!clock;
         alternate=!alternate;             
      }
      bit>>=1;
      if (bit==0)
      {
         bit=128;
         ctr++; //next byte
         if (ctr==7)
         {
            ctr=0;
            have_data=TRUE;
         }
      }
      break;
   }
}

void main()
{
   int ctr;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4); //Gives FOSC/16
   enable_interrupts(global);
   enable_interrupts(INT_IOC_A0);
   while (TRUE)
   {
      state=HEADER;
      while (have_data==FALSE)
         ; //wait for data
      //here deal with data
      delay_cycles(1);
      //set flag back to 0 to start search for next packet and set have_data
      //to false.
   }   
}


The HANGE and SYNCPULSE constants may be wrong, since I just measured
from your displayed graphs.
bulut_01



Joined: 24 Feb 2024
Posts: 213

View user's profile Send private message

PostPosted: Wed Feb 05, 2025 9:24 am     Reply with quote

thank you mr Ttelmah I will test it as soon as possible
PrinceNai



Joined: 31 Oct 2016
Posts: 527
Location: Montenegro

View user's profile Send private message

PostPosted: Wed Feb 05, 2025 11:49 am     Reply with quote

I wrote something to decode your kind of data. It should work. There is also a code I used for test transmitter, copying pattern from one of your pictures. It will be attached at the end. I used 18f46k22 for this, so you'll need to change a couple of things. First thing is the location of INTDEG. Second thing is the number of DECODED bytes you expect. I only coded for 3.
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 3                                            // number of DECODED bytes to receive
#define TE 600                                                       // duration of one bit in us, change as needed
#define PREAMBLE_MAX 8*TE
#define PREAMBLE_MIN 6*TE                                            // we expect a 7 bit preamble, make some room for error
#define TRANSITION_MIN 1.5*TE                                        // same here when sampling
#define TRANSITION_MAX 2.5*TE

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

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

int8 ByteCounter = 0;                                                // keeps track about which byte we are filling in
int8 BitPosition = 0;                                                // bit position of the incoming data
int8 DataReceived = 0;                                               // flag to inform main data was received and decoded
                                                       
// switch
enum {GotRisingEdge = 1, GotFallingEdge, SampleData};
int8 DecodeSwitch = GotRisingEdge;
// Timer
int16 TimerValue;
int8 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
      output_high(PIN_D6);
   }
   else{
      INTDEG = 1;                                                    // activate interrupt on rising edge
      output_low(PIN_D6);
   }
}

// ------------------------------------------------------------------
void ClearBuffer (void){
   DecodedInputData[0] = 0x00;                                       // lazy :-)
   DecodedInputData[1] = 0x00;
   DecodedInputData[2] = 0x00;
}


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

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

#INT_TIMER0
void  TIMER0_isr(void)
{
   Overflow++;                                                       // count timer 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)                                             // switch to receive and decode Mancester encoded data
   {
// ------------------------------------------------------------------
// wait for a rising edge from the transmitter, this state also serves as a reset. Always come here with L_TO_H transition set!

      case GotRisingEdge:                                            // we have a rising edge, could be start of the preamble
      {           
         set_timer0(0);                                              // reset timer
         Overflow = 0;
         BitPosition = 0;
         ByteCounter = 0;
         CurrentByte = 0;
         DataReceived = 0;         
         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, so last transition was H_to_L
      {
         ext_int_edge(0, L_TO_H);                                    // prepare for interrupt on a L_TO_H edge       
         TimerValue = get_timer0();
         
         if(TimerValue > PREAMBLE_MIN && TimerValue < PREAMBLE_MAX) {// bingo, we have a preamble
            set_timer0(0);                                           // preset timer
            Overflow = 0;
            DecodeSwitch = SampleData;                               // go sampling the input         
         }         
         else{                                                       // 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 happen in the middle of a bit.
// That can either be the first transition, if two subsequent symbol have different value, or it can
// be the second transition, if two subsequent symbols have the same value. We are using timer reading
// to find out which one just occured. If it is the one we are looking for, sample the input and store
// to the correct location in the data buffer
// On start we come here on rising edge, meaning there was a transition 0-1

      case SampleData:
      {
         ToggleIntEdge();                                            // change the active edge of the interrupt for sampling       
         TimerValue = get_timer0();
// check what kind of a transition we have. If the transition happened in
// a time frame of 0,5*TE to 1,5*TE it is considered that this bit has the same
// value as the previous and that we need to wait for another interrupt for the sampling
                                                                           
// time between two edges is correct, take sample. This test is intentionally in the first place
// so it gets serviced as fast as possible, since the timer is already running

         if(Overflow == 0 && TimerValue >= TRANSITION_MIN && TimerValue <= TRANSITION_MAX){  // this is the one we are looking for, sample and store the data
            set_timer0(0);                                           // reset timer for the next pair

// REVERSE DECODING LOGIC AS NEEDED HERE!!!!! COMMENT THE WRONG IF OUT!!!!     
       
            if(input_state(pin_B0) == 0){
//            if(input_state(pin_B0) == 1){
               bit_set(CurrentByte, 7 - BitPosition);                // sample. Set appropriate bit if needed, leave 0 otherwise               
               }
            BitPosition++;
            if(BitPosition > 7){                                     // one byte of data received
               BitPosition = 0;
               DecodedInputData[ByteCounter] = CurrentByte;          // store the data into the buffer
               CurrentByte = 0;                                      // prepare variable for next byte
               ByteCounter++;                                        // increment byte counter for a correct position
               
               if (ByteCounter == NUMBER_OF_BYTES){                  // if all the bytes are in
                  ext_int_edge(0, L_TO_H);
                  DataReceived = 1;                                  // signal that to main
                  DecodeSwitch = GotRisingEdge;                      // and reset state machine
               }  // if byte counter
            }     // if bit position 
         
         }        // end sampling                                                                     
                                                                                                                                                                                                           
// time between two edges too short for sampling, it may be transition between two symbols with the same value                                                                   
         else if(Overflow == 0 && TimerValue < TRANSITION_MIN){      // the transition came too soon for sampling, exit but stay in the same case
            delay_cycles(1);
         }
         
// time between two edges to long for a valid bit, reset         
         else{                                                       // time between two transitions is 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)
   {



   }

}


Transmitter:
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;

////////////////////////// FUNCTIONS ////////////////////////////////
// ------------------------------------------------------------------
void i (void){
// 1
   output_high(PIN_B5);
   delay_us(600);
   output_low(PIN_B5);
   delay_us(600);
}
// ------------------------------------------------------------------

void o (void){
// 0
   output_low(PIN_B5);
   delay_us(600);
   output_high(PIN_B5);
   delay_us(600);
}
// ------------------------------------------------------------------

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(PIN_B5);
   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(PIN_B5);
         delay_ms(2000);
           
      // sync -------------------------------------------------------------
         for(k= 0; k < 5; k++){
            output_high(PIN_B5);
            delay_us(1800);
            output_low(PIN_B5);
            delay_us(1800);
         }
         
      // preamble ---------------------------------------------------------
         output_high(PIN_B5);
         delay_us(4200);
         output_low(PIN_B5);
         
      // leading 0
         delay_us(600);
     
      // data -------------------------------------------------------------
     
      // byte1 ----------
      // 1
         i();
      // 1
         i();     
      // 1
         i();
      // 1
         i();
         
      // byte2 ----------
      // 1
         i(); 
      // 1
         i();
      // 1
         i();
      // 1
         i();
         
      // byte3 ---------
      // 0
         o();
      // 0
         o();   
      // 0
         o();
      // 0
         o();
         
      // byte4 ---------
      // 0
         o();     
      // 0
         o();
      // 0
         o();     
      // 0
         o();
         
      // byte5 ----------
      // 0
         o();
      // 1
         i();
      // 0
         o();
      // 1
         i();
         
      // byte6 ----------
      // 1
         i();
      // 0
         o();
      // 1
         i();
      // 0
         o();
           
      // pause ------------------------------------------------------------
         output_low(PIN_B5);
         delay_ms(500);
         enable_interrupts(INT_TIMER0);
   
      }
   
//////////////////
   }

}
bulut_01



Joined: 24 Feb 2024
Posts: 213

View user's profile Send private message

PostPosted: Fri Feb 07, 2025 12:25 pm     Reply with quote

mr. Ttelmah First of all, thank you for the code you wrote, but I made the settings and the code did not work. My bit size is 640 us, according to your ''change'' setting, it makes 640 x 2 = 1280 us, I made the setting accordingly, sync 2.5 ms x 7. I am publishing the code, I remembered it in the picture, where did I miss it ?

Last edited by bulut_01 on Mon Feb 24, 2025 1:42 pm; edited 2 times in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19739

View user's profile Send private message

PostPosted: Fri Feb 07, 2025 12:33 pm     Reply with quote

The sync width needed, is half way between the clock rate of the header
bits and the single bit that is the sync pulse.
The time needed for the CHANGE value is half way between the width of
a full clock bit and the half clock bits that happen when the signal is
changing from matching the Manchester clock and out of sync with the
clock.
bulut_01



Joined: 24 Feb 2024
Posts: 213

View user's profile Send private message

PostPosted: Fri Feb 07, 2025 1:16 pm     Reply with quote

Ttelmah wrote:
The sync width needed, is half way between the clock rate of the header
bits and the single bit that is the sync pulse.
The time needed for the CHANGE value is half way between the width of
a full clock bit and the half clock bits that happen when the signal is
changing from matching the Manchester clock and out of sync with the
clock.


Where is the header duration in the code? I set change to 1250 as you said, I am making a mistake somewhere and the code is not working.
bulut_01



Joined: 24 Feb 2024
Posts: 213

View user's profile Send private message

PostPosted: Fri Feb 07, 2025 1:23 pm     Reply with quote

sync 1 bit 2500 us 2500 / 2 = ''change 1250'' is calculated as.
How do you calculate SYNCPULSE?
bulut_01



Joined: 24 Feb 2024
Posts: 213

View user's profile Send private message

PostPosted: Fri Feb 07, 2025 2:06 pm     Reply with quote

mr.Ttelmah Where am I making mistakes ?
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 ... 13, 14, 15 ... 18, 19, 20  Next
Page 14 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