Data & asynchronous transmission to use in wireless communications

Hello once again.... :slight_smile:

Finally i got a steady transmission signal with steady 125kHz. So i need the receiver to actually receive something.
But, surprise...new problems ...

What i was trying to do was get The timer2 to have interrupts every 8us (125kHz) and i managed to do it:
(RxPin is 4 and it's connected to a simple switch, pinT2 is 5 and i'm using Arduino UNO)

VLC.cpp

static char RxPin = 4;
static char pinT2 = 5;


static int rx_sample = 0;
static int rx_last_sample = 0;
static uint8_t rx_count = 0;
static uint8_t rx_sync_count = 0;
static uint8_t rx_mode = RX_MODE_IDLE;

static unsigned int rx_manBits = 0; //the received manchester 32 bits
static unsigned char rx_numMB = 0; //the number of received manchester bits
static unsigned char rx_curByte = 0;

static unsigned char rx_maxBytes = 2;
static unsigned char rx_default_data[2];
static unsigned char* rx_data = rx_default_data;

void MANRX_SetRxPin(char pin)
{
  RxPin = pin;
  	if (pin <=7){
		RxPin = pin;			// user sets the digital pin as input
		DDRD &= ~(1<<RxPin);	//pinMode(RxPin, INPUT);
	}	
	else if ((pin >= 8) || (pin <= 13)){
		RxPin = pin - 8;		// user sets the digital pin as input
		DDRB &= ~(1<<RxPin);	//pinMode(RxPin, INPUT);
	}
}//end of set reception pin

void MANRX_SetupReceive()
{
	DDRD &= ~(1<<RxPin);	// default pinMode(RxPin, INPUT);
	/*
	Timer 2 is used with a ATMega328. The base clock is 16MHz. 
	 - If we don't use any clock divider which gives 62.5 nS per count.
	 - If we use /8 as clock divider resulti is 0.5 usS per count.

	PS = 1 (Prescaler)
	1 / (16,000,000 / PS) = 62.5nS/count

	PS = 8 (Prescaler)
	1 / (16,000,000 / PS) = 0.5uS/count

	NRZ frequency is half the Tx signal (Manchester Encoded)
	So, F_NRZ = 125kHz => 8us/bit (time of each bit)
	PS=1 => 8us/62.5ns = 128
	PS=1 => 8us/0.5us = 16
	*/

  TCCR2A = _BV(WGM21); // reset counter on match
  TCCR2B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));// reset clock select register, and starts the clock
  TCCR2B |= _BV(CS11);//counts every 0.5usec with 16 Mhz clock    
  OCR2A = 15; // interrupt every 16 counts (0->15)
  TIMSK2 = _BV(OCIE2A); // Turn on interrupt
  TCNT2 = 0; // Set counter to 0
}

void MANRX_BeginReceive(void)
{
  rx_maxBytes = 2;
  rx_data = rx_default_data;
  rx_mode = RX_MODE_PRE;
}

void test_t2(char pin)
{
	if (pin <=7){
		pinT2 = pin; // user sets the digital pin as output
		DDRD = DDRD | B0000001 | (1<<pinT2);	//pinMode(TxPin, OUTPUT);
		PORTD |= _BV(pinT2);
	}
	else if ((pin >= 8) || (pin <= 13)){
		pinT2 = pin - 8; // user sets the digital pin as output
		DDRB = DDRB | B0000001 | (1<<pinT2);	//pinMode(TxPin, OUTPUT);
		PORTB |= _BV(pinT2);
	}
}


unsigned int MANRX_GetMessage(void)
{
  return (((int)rx_data[0]) << 8) | (int)rx_data[1];
}


ISR(TIMER2_COMPA_vect)
{
	PORTD |= (1<<pinT2);
	unsigned char test = (PIND & (1<<RxPin));
	rx_data[1] = test;
	rx_data[0] = 0x00;
	PORTD &= ~(1 << pinT2);
}

VLC.h - class Manchester refers to transmission and it's working

/*
This code is based on the Atmel Corporation Manchester
Coding Basics Application Note.

http://www.atmel.com/dyn/resources/prod_documents/doc9164.pdf

Quotes from the application note:

"Manchester coding states that there will always be a transition of the message signal
at the mid-point of the data bit frame.
What occurs at the bit edges depends on the state of the previous bit frame and
does not always produce a transition. A logical “1” is defined as a mid-point transition
from low to high and a “0” is a mid-point transition from high to low.
*/

#ifndef VLC_h
#define VLC_h

#define TxDefault 8 //the digital pin to use to transmit data
#define RxDefault 4 //the digital pin to use to receive data


#define RX_MODE_PRE 0
#define RX_MODE_SYNC 1
#define RX_MODE_DATA 2
#define RX_MODE_MSG 3
#define RX_MODE_IDLE 4

#define TimeOutDefault -1 //the timeout in msec default blocks

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#include <pins_arduino.h>
#endif

class MANCHESTERClass
{
  public:
    MANCHESTERClass(); //the constructor
	void SetPW(unsigned int interval); //  user sets the pulse width of half bit
    void SetTxPin(char pin); //set the arduino digital pin for transmit. default 4.
    void Transmit(unsigned int data); //transmit 16 bits of data
    void TransmitBytes(unsigned char numBytes, unsigned char *data); // transmit a byte array

    
  private:
    unsigned char TxPin;
	unsigned int HALF_BIT_INTERVAL;
};//end of class MANCHESTER

// Cant really do this as a real C++ class, since we need to have
// an ISR
extern "C"
{
	//for debugging only - tests T2 interrupts
	extern void test_t2(char pin);

    //set the arduino digital pin for receive. default 4.
    extern void MANRX_SetRxPin(char pin);
    
    //begin the timer used to receive data
    extern void MANRX_SetupReceive();
	
	// begin receiving 16 bits
    extern void MANRX_BeginReceive(void);


    
    // fetch the received message
    extern unsigned int MANRX_GetMessage();

}

extern MANCHESTERClass MANCHESTER;

#endif

MAIN PROGRAM

#include <VLC.h>
#include <avr/io.h>    

#define RxPin 4
#define pinT2 5

void setup()
{
  test_t2(pinT2); // tests T2 frequency interrupts
  
  MANRX_SetRxPin(RxPin); // Set digital TX pin
  MANRX_SetupReceive(); // Prepare interrupts
  MANRX_BeginReceive(); // Begin receiving data
  
  Serial.begin(115200);   // Debugging only
}//end of setup

void loop()
{
  unsigned int data = MANRX_GetMessage();
  MANRX_BeginReceive();
  //unsigned int data = 0x0010;
  Serial.println(data);
}//end of loop

So there are a couple of things happenning that i really don't understand.

(1) When i erase this 1st line (while keeping the second) my interruptions appear every 250us instead of 8us. What am i missing here?

TCCR2B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));// reset clock select register, and starts the clock
  TCCR2B |= _BV(CS11);//counts every 0.5usec with 16 Mhz clock

(1.1) While the 1st line is deleted i can change switch on pin 4 and serial monitor updates accordingly and that is fine. But why doesn't update when that 1st line is present?

(2) Now i add this line to ISR:

ISR(TIMER2_COMPA_vect)
{
	[b]TCNT2 = 0; // Set counter to 0[/b]
	PORTD |= (1<<pinT2);
        .......
}

why the serial monitor updates then stops nad only updates again when i reset?

(2.1) And why he updates a few times pin4 status when he is high and only half dozen when it's low? :S

(3)Wasn't supposed to interrupts have the same timming? Depending on the code i get less frequency....
For example...the code in ISR from VLC.cpp drops my freq to 120kHz and it even have 1/10 of what is needed.

Plz enlight me...

Thanks for support,
Fernando Oliveira