[solved] Can't use turnOffPWM() macro

Hi

I'm trying to build my own 433Mhz transmission protocol and library (inspired by rcswitch).

I want to achieve a high data rate (thus high pin state change frequency) but when I use digitalWrite, I can't get fast enough pin changes to have a clear signal.
I read here and there that digitalWrite was looking for the register & bit at every call (which is a logical thing) but I wanted to bypass this by searching for them once, storing the data and using them later.

So copied the digitalWrite code, used the searching part in my setTransmitterPin() function and will use the setting part in my transmit() funciton.

However, as I need to turn off pwm for a pin in order to set it to 1, I used turnOffPWM() macro (same as digitalWrite function) but I get the following error :

In member function 'void Radio::setTransmitterPin(int16_t)':

radio.cpp:16: error: 'turnOffPWM' was not declared in this scope

     if (timer != NOT_ON_TIMER) turnOffPWM(timer);

                                                ^

exit status 1
'turnOffPWM' was not declared in this scope

Here is the code :

#include "Arduino.h"
#include <EEPROM.h>

#ifndef _radio_h
#define _radio_h

#define pulseLength 30 // microsecs per pulse
#define offsetTolerance 5 // microsecs per pulse
#define modeQuery 0b0
#define modeReply 0b1

#define signPositive 0
#define signNegative 1

#define codeDiscover 1
#define codeRequestConfig 2
#define codeRequestId 3
#define codeRequestSeed 4



class Radio {
 public:

 typedef struct Pulses {
 int16_t high;
 int16_t low;
 };

 typedef struct Message {
 uint16_t source;       // 16 bits
 uint16_t destination; // 16 bits
 uint8_t mode;         // 1 bit : 0 query / 1 reply
 uint8_t code;         // 4 bits : action code
 uint8_t sign; // 1 bit : 0 positive / 1 negative
 uint16_t value; // 16 bits max
 uint16_t seed;         // 16 bits
 uint16_t hash;     // 16 bits
 };

 Radio();
 void setTransmitterPin(int16_t pin);
 void setReceiverPin(int16_t pin);
 void send(Message message, byte secured = 1);
 static void init();
 int8_t isAvailable();
 void resetAvailable();
 Message getMessage();

 private:
 Pulses start = {10, 1};
 Pulses stop = {10, 1};
 Pulses separator = {10, 10};
 Pulses one = {3, 1};
 Pulses zero = {1, 3};
 
 uint8_t transmitterBit;
 uint8_t *transmitterPort;

 uint8_t receiverPin;
 uint8_t available;
 static Message message;
 uint16_t neighborNodes[];
 uint16_t masterAddress;
 uint16_t masterRoute[3];
 void requestConfig(uint16_t node);
 void transmit(uint16_t value);
 void transmit(uint8_t value);
 void transmit(Pulses pulses);
 static void receive();
 static void parseMessage();
 static inline unsigned int diff(int16_t A, int16_t B);
};

#endif
#include "radio.h"

Radio::Radio(){
    this->receiverPin = -1;
    this->available = 0;
}

void Radio::setTransmitterPin(int16_t pin){
    this->transmitterBit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    if (port == NOT_A_PIN) return;
    this->transmitterPort = portOutputRegister(port);
    // If the pin that support PWM output, we need to turn it off
    // before doing a digital write.
    uint8_t timer = digitalPinToTimer(pin);
    if (timer != NOT_ON_TIMER) turnOffPWM(timer);
}

void Radio::setReceiverPin(int16_t pin){
    this->receiverPin = pin;
}

static void Radio::init(){

}

void Radio::transmit(uint16_t value){
    char position = (sizeof(value) * 8) - 1;
    while(!(value & (1 << position))){
        position--;
    }
    while (position >= 0){
        this->transmit(value & (1 << position) ? Radio::one : Radio::zero);
        position--;
    }
}

void Radio::transmit(uint8_t value){
    char position = (sizeof(value) * 8) - 1;
    while(!(value & (1 << position))){
        position--;
    }
    while (position >= 0){
        this->transmit(value & (1 << position) ? Radio::one : Radio::zero);
        position--;
    }
}

void Radio::transmit(Radio::Pulses pulses){
    uint8_t oldSREG = SREG;
    cli();
    *this->transmitterPort |= this->transmitterBit;
    delayMicroseconds(pulses.high * pulseLength);
    *this->transmitterPort &= ~this->transmitterBit;
    SREG = oldSREG;
    delayMicroseconds(pulses.low * pulseLength);
}

void Radio::send(Message message, byte secured = 1){
    Radio::transmit(Radio::start);

    Radio::transmit(message.source);
    Radio::transmit(Radio::separator);

    Radio::transmit(message.destination);
    Radio::transmit(Radio::separator);

    Radio::transmit(message.mode);
    Radio::transmit(Radio::separator);

    Radio::transmit(message.code);
    Radio::transmit(Radio::separator);

    Radio::transmit(message.sign);
    Radio::transmit(Radio::separator);

    Radio::transmit(message.value);
    Radio::transmit(Radio::separator);
    
    Radio::transmit(message.seed);
    Radio::transmit(Radio::separator);
    
    Radio::transmit(message.hash);
    Radio::transmit(Radio::separator);

    Radio::transmit(Radio::stop);
}

int8_t Radio::isAvailable(){
    return this->available;
}

void Radio::resetAvailable(){
    this->available = 0;
}

Radio::Message Radio::getMessage(){
    return this->message;
}

void Radio::requestConfig(uint16_t node){

}

static void Radio::receive(){

}

static void Radio::parseMessage(){

}

static inline unsigned int Radio::diff(int16_t A, int16_t B){
    return abs(A - B);
}

Thanks for reading me

Is turnOffPWM a macro or a function ?

turnOffPWM is a function, not a macro. It's defined as static in wiring_digital.c. That means it can only be accessed from that translation unit, and not your sketch. So you would need to remove the static keyword from the definition in wiring_digital.c. Since turnOffPWM was not intended to be used outside wiring_digital.c, there is no function prototype for it in Arduino.h. So you would also need to add a function prototype to your sketch. Since wiring_digital.c is a C file and the sketch is C++, you also need to wrap the function prototype in extern "C" {}:

extern "C"{
void turnOffPWM(uint8_t timer);
}

In order to avoid editing the core library files, you might prefer to simply define turnOffPWM in your own code. turnOffPWM uses the macro cbi, which is defined in wiring_private.h so you will need to add an #include directive for wiring_private.h.

pert:
Since wiring_digital.c is a C file and the sketch is C++

I just noticed you are writing a library, not a sketch, but the library is C++ so the same holds true.

pert:
turnOffPWM is a function, not a macro. It's defined as static in wiring_digital.c. That means it can only be accessed from that translation unit, and not your sketch. So you would need to remove the static keyword from the definition in wiring_digital.c. Since turnOffPWM was not intended to be used outside wiring_digital.c, there is no function prototype for it in Arduino.h. So you would also need to add a function prototype to your sketch. Since wiring_digital.c is a C file and the sketch is C++, you also need to wrap the function prototype in extern "C" {}:

extern "C"{

void turnOffPWM(uint8_t timer);
}




In order to avoid editing the core library files, you might prefer to simply define turnOffPWM in your own code. turnOffPWM uses the macro cbi, which is defined in wiring_private.h so you will need to add an #include directive for wiring_private.h.

Or not define turnOffPWM and use it's code directly since I will have no other use :

    if (timer != NOT_ON_TIMER){
        switch (timer){
            case TIMER1A:   cbi(TCCR1A, COM1A1);    break;
            case TIMER1B:   cbi(TCCR1A, COM1B1);    break;
            case  TIMER0A:  cbi(TCCR0A, COM0A1);    break;
            case  TIMER0B:  cbi(TCCR0A, COM0B1);    break;
            case  TIMER2A:  cbi(TCCR2A, COM2A1);    break;
            case  TIMER2B:  cbi(TCCR2A, COM2B1);    break;
        }
    }

Thanks it compiles successfully.

I tried it on my arduino, now I get a very very low signal. Am I missing something else ?

EDIT : I'm using my PC and Audacity as signal analyzer and when I record with my front input jack, it way lower than the back input jack. Now I have the perfect signal.

Thanks guys !