OneWireSlave.h ошибка :"cannot call member function ‘ ’ without object"

Soy

✩✩✩✩✩✩✩
12 Мар 2021
12
0
Парни, такое дело, есть библиотека OneWireSlave, и решил я внутри ее "похимичить" приклеив туда обработку прерывания, чтобы waitForRequest не тормозила основную программу в Attiny85. К слову сказать не чего бы не делал, если бы на Attiny85 сразу заработало (на Ардуино Нано работало все без внешнего прерывания). Вообщем сделал так: в OneWireSlave.cpp вставил строки:

C++:
#include "OneWireSlave.h"
//--------- вставил, что бы не заморачиваться отдельно с регистрами для дуньки и тиньки
#if defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny13__)

#define EICRA   _SFR_IO8(0x35)
#define ISC00 0
#define ISC01 1
#define EIMSK   _SFR_IO8(0x3B)
#define INT0    6
#define EIFR _SFR_IO8(0x3A)
#define INTF0   6
#endif
//------------------- это взято  из другой библы ----------------------------
//Pin interrupt
#define EN_INT {EIMSK|=(1<<INT0);EIFR|=(1<<INTF0);}  //enable interrupt
#define DIS_INT  EIMSK&=~(1<<INT0);  //disable interrupt
#define SET_RISING EICRA=(1<<ISC01)|(1<<ISC00);  //set interrupt at rising edge
#define SET_FALLING {EICRA &= ~(1 << ISC00);EICRA|=(1<<ISC01);} //set interrupt at falling edge
#define CHK_INT_EN (EIMSK&(1<<INT0))==(1<<INT0) //test if interrupt enabled
#define PIN_INT ISR(INT0_vect)  // the interrupt service routine
//--------------------------------------------------------------------
volatile uint8_t mode; //state
void waitProcess_(uint8_t tmode);
void (*OneWireSlave::rxCallback_)();
uint8_t OneWireSlave::errno;
Pin OneWireSlave::pin_;

PIN_INT {
    OneWireSlave::waitProcess_(mode);
}

OneWireSlave::OneWireSlave(uint8_t pin) {
    pin_ = Pin(pin);
    //pin_bitmask = digitalPinToBitMask(pin);
    //baseReg = portInputRegister(digitalPinToPort(pin));
}

void OneWireSlave::begin() { //эту ф-цию вставил
    cli();
    pin_.inputMode();
    SET_FALLING;
    EN_INT;
    sei(); // enable interrupts
}

void OneWireSlave::waitProcess_(uint8_t tmode)// и эту
{
    unsigned long time_stamp;
    uint8_t delta=25;
    errno = ONEWIRE_NO_ERROR;
    DIS_INT;// запрет прерывания INT0;
    switch (mode) {
        case 0:
            time_stamp = micros() + 540;
            while (pin_.read() == 0) {
              if (micros() > time_stamp) {
                  errno = ONEWIRE_VERY_LONG_RESET;//импульс RESET оказался слишком длинным (возможно это не RESET, а что-то другое).
                  return;
              }
           }
           if ((time_stamp - micros()) > 70) {
              errno = ONEWIRE_VERY_SHORT_RESET;//импульс RESET оказался слишком коротким. Такая ошибка может появиться, если при ожидании RESET сигнала другое устройство начало передачу данных.
              return;
           }
           delayMicroseconds(30);
           //пришел имп.сброса (мастер начал сработу с шиной)
           //посылаем PRESENCE
           if (OneWireSlave::presence() ) rxCallback_();  // вот тут проблема
            /* ошибка
             ...Arduino\libraries\OneWireSlave\OneWireSlave.cpp:In static member function 'static void OneWireSlave::waitProcess_(uint8_t)':
             ...Arduino\libraries\OneWireSlave\OneWireSlave.cpp:161:33: error: cannot call member function 'bool OneWireSlave::presence()' without object
               if (OneWireSlave::presence() ) rxCallback_();                  
            */
            break;
        case 1:
             //
            break;
    }
     
}

//ф-ция presence() - родная, ее не трогал
bool OneWireSlave::presence(uint8_t delta) {
    errno = ONEWIRE_NO_ERROR;
    cli();
    pin_.writeLow();
    pin_.outputMode();// drive output low
    sei();
    delayMicroseconds(120);
    cli();
     pin_.inputMode(); // allow it to float
    sei();
    delayMicroseconds(300 - delta);
    if ( !pin_.read()) {  
        errno = ONEWIRE_PRESENCE_LOW_ON_LINE;
        return FALSE;
    } else
        return TRUE;
}
bool OneWireSlave::presence() {
    return presence(25);
}
//остальное все пока по дефолту осталось
теперь то что вставил в код библы OneWireSlave.h:

C++:
#ifndef _OneWireSlave_h_
#define _OneWireSlave_h_

#include "Arduino.h"
#include "utility/LowLevel.h"



// You can exclude CRC checks altogether by defining this to 0
#ifndef ONEWIRESLAVE_CRC
#define ONEWIRESLAVE_CRC 1
#endif

// Select the table-lookup method of computing the 8-bit CRC
// by setting this to 1.  The lookup table no longer consumes
// limited RAM, but enlarges total code size by about 250 bytes
#ifndef ONEWIRESLAVE_CRC8_TABLE
#define ONEWIRESLAVE_CRC8_TABLE 0
#endif

#define FALSE 0
#define TRUE  1

#define ONEWIRE_NO_ERROR 0
#define ONEWIRE_READ_TIMESLOT_TIMEOUT 1
#define ONEWIRE_WRITE_TIMESLOT_TIMEOUT 2
#define ONEWIRE_WAIT_RESET_TIMEOUT 3
#define ONEWIRE_VERY_LONG_RESET 4
#define ONEWIRE_VERY_SHORT_RESET 5
#define ONEWIRE_PRESENCE_LOW_ON_LINE 6

class OneWireSlave {
public:
    enum ReceiveEvent
    {
        RE_Reset, //!< The master has sent a general reset
        RE_Byte, //!< The master just sent a byte of data
        RE_Error //!< A communication error happened (such as a timeout) ; the library will stop all 1-wire activities until the next reset
    };
   
    OneWireSlave(uint8_t pin);
    void setRom(unsigned char rom[8]);
    void begin();
    // ---------- эти ф-ции добавил ----------------------------------------
    void setCallbackRX(void (*callback)()) { rxCallback_ = callback; }
    static void(*rxCallback_)();
    static void waitProcess_(uint8_t tmode);
    //----------------------------------------------------------------------
    bool waitForRequest(bool ignore_errors);
    bool waitReset(uint16_t timeout_ms);
    bool waitReset();
    bool presence(uint8_t delta);
    bool presence();
    bool search();
    uint8_t sendData(char buf[], uint8_t data_len);
    uint8_t recvData(char buf[], uint8_t data_len);
    void send(uint8_t v);
    uint8_t recv(void);
    void sendBit(uint8_t v);
    uint8_t recvBit(void);
#if ONEWIRESLAVE_CRC
    static uint8_t crc8(char addr[], uint8_t len);
#endif
    static uint8_t errno;// пришлось сделать Static, иначе таже ошибка
   
private:
   
    bool recvAndProcessCmd();
    bool waitTimeSlot();
    char rom[8];
    // interrupt handlers
    static Pin pin_;
};

#endif
ну, и последняя библа LowLevel.h ( взята отсюда: https://github.com/ntruchsess/OneWireArduinoSlave)

C++:
#ifndef _LowLevel_h
#define _LowLevel_h

#include <inttypes.h>

#ifdef VS_INTELLISENSE
#define __attribute__(...)
#define digitalPinToPort(pin) 0
#define digitalPinToBitMask(pin) 0
#define portInputRegister(arg1) 0
#endif

#if ARDUINO >= 100
#include "Arduino.h"       // for delayMicroseconds, digitalPinToBitMask, etc
#else
#include "WProgram.h"      // for delayMicroseconds
#include "pins_arduino.h"  // for digitalPinToBitMask, etc
#endif

#if defined(__AVR__)
#define PIN_TO_BASEREG(pin)             (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint8_t
#define IO_REG_ASM asm("r30")
#define DIRECT_READ(base, mask)         (((*(base)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask)   ((*((base)+1)) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask)  ((*((base)+1)) |= (mask))
#define DIRECT_WRITE_LOW(base, mask)    ((*((base)+2)) &= ~(mask))
#define DIRECT_WRITE_HIGH(base, mask)   ((*((base)+2)) |= (mask))

#if defined (__AVR_ATtiny85__)
#define CLEARINTERRUPT GIFR |= (1 << INTF0)
#include "UserTimer.h" //ATtiny-support based on TinyCore1 Arduino-core for ATtiny at http://github.com/Coding-Badly/TinyCore1.git
__attribute__((always_inline)) static inline void UserTimer_Init( void )
{
    UserTimer_SetToPowerup();
    UserTimer_SetWaveformGenerationMode(UserTimer_(CTC_OCR));
}
__attribute__((always_inline)) static inline void UserTimer_Run(short skipTicks)
{
    UserTimer_SetCount(0);
    UserTimer_SetOutputCompareMatchAndClear(skipTicks);
    UserTimer_ClockSelect(UserTimer_(Prescale_Value_64));
}
#define UserTimer_Stop() UserTimer_ClockSelect(UserTimer_(Stopped))

#elif defined (__AVR_ATmega328P__)
#define CLEARINTERRUPT EIFR |= (1 << INTF0)
#define USERTIMER_COMPA_vect TIMER1_COMPA_vect

__attribute__((always_inline)) static inline void UserTimer_Init( void )
{
    TCCR1A = 0;
    TCCR1B = 0;
    // enable timer compare interrupt
    TIMSK1 |= (1 << OCIE1A);
}
__attribute__((always_inline)) static inline void UserTimer_Run(short skipTicks)
{
    TCNT1 = 0;
    OCR1A = skipTicks;
    // turn on CTC mode with 64 prescaler
    TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10);
}
#define UserTimer_Stop() TCCR1B = 0
#endif

#elif defined(__MK20DX128__) || defined(__MK20DX256__)
#define PIN_TO_BASEREG(pin)             (portOutputRegister(pin))
#define PIN_TO_BITMASK(pin)             (1)
#define IO_REG_TYPE uint8_t
#define IO_REG_ASM
#define DIRECT_READ(base, mask)         (*((base)+512))
#define DIRECT_MODE_INPUT(base, mask)   (*((base)+640) = 0)
#define DIRECT_MODE_OUTPUT(base, mask)  (*((base)+640) = 1)
#define DIRECT_WRITE_LOW(base, mask)    (*((base)+256) = 1)
#define DIRECT_WRITE_HIGH(base, mask)   (*((base)+128) = 1)

#elif defined(__SAM3X8E__)
// Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due.
// http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268
// If you have trouble with OneWire on Arduino Due, please check the
// status of delayMicroseconds() before reporting a bug in OneWire!
#define PIN_TO_BASEREG(pin)             (&(digitalPinToPort(pin)->PIO_PER))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_ASM
#define DIRECT_READ(base, mask)         (((*((base)+15)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask)   ((*((base)+5)) = (mask))
#define DIRECT_MODE_OUTPUT(base, mask)  ((*((base)+4)) = (mask))
#define DIRECT_WRITE_LOW(base, mask)    ((*((base)+13)) = (mask))
#define DIRECT_WRITE_HIGH(base, mask)   ((*((base)+12)) = (mask))
#ifndef PROGMEM
#define PROGMEM
#endif
#ifndef pgm_read_byte
#define pgm_read_byte(addr) (*(const uint8_t *)(addr))
#endif

#elif defined(__PIC32MX__)
#define PIN_TO_BASEREG(pin)             (portModeRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_ASM
#define DIRECT_READ(base, mask)         (((*(base+4)) & (mask)) ? 1 : 0)  //PORTX + 0x10
#define DIRECT_MODE_INPUT(base, mask)   ((*(base+2)) = (mask))            //TRISXSET + 0x08
#define DIRECT_MODE_OUTPUT(base, mask)  ((*(base+1)) = (mask))            //TRISXCLR + 0x04
#define DIRECT_WRITE_LOW(base, mask)    ((*(base+8+1)) = (mask))          //LATXCLR  + 0x24
#define DIRECT_WRITE_HIGH(base, mask)   ((*(base+8+2)) = (mask))          //LATXSET + 0x28

#else
#error "Please define I/O register types here"
#endif

class Pin
{
private:
    volatile IO_REG_TYPE *reg_;
    IO_REG_TYPE mask_;
    byte interruptNumber_;
    byte pinNumber_;

public:
    Pin()
        : mask_(0)
        , reg_(0)
        , interruptNumber_((byte)-1)
        , pinNumber_(255)
    { }

    Pin(uint8_t pin)
    {
        pinNumber_ = pin;
        mask_ = PIN_TO_BITMASK(pin);
        reg_ = PIN_TO_BASEREG(pin);
       
        switch (pin)
        {
        case 2: interruptNumber_ = 0; break;
        case 3: interruptNumber_ = 1; break;
        default: interruptNumber_ = (byte)-1;
        }
    }

    inline byte getPinNumber() { return pinNumber_; }

    inline void inputMode() { DIRECT_MODE_INPUT(reg_, mask_); }
    inline void outputMode() { DIRECT_MODE_OUTPUT(reg_, mask_); }

    inline bool read() { return DIRECT_READ(reg_, mask_) == 1; }
    inline void writeLow() { DIRECT_WRITE_LOW(reg_, mask_); }
    inline void writeHigh() { DIRECT_WRITE_HIGH(reg_, mask_); }
    inline void write(bool value) { if (value) writeHigh(); else writeLow(); }

    inline void attachInterrupt(void (*handler)(), int mode)
    {
        CLEARINTERRUPT;  // очистить все ожидающие прерывания (мы хотим вызывать обработчик только для прерываний, происходящих после его присоединения)
        ::attachInterrupt(interruptNumber_, handler, mode);
    }
    inline void detachInterrupt() { ::detachInterrupt(interruptNumber_); }
};

#endif
собственно по вопросу "зачем заморачиваться, почему сразу всю не взял?" - пытался, но во-первых ни хрена не работает код из примера, во-вторых сжирает память у Digisparka, ну и в третьих используются прерывания Timer0, что конфликтует с сервой, которой мне необходимо управлять по шине 1-Wire.

Вообщем ломаю голову неделю, что только не пробовал эта ошибка постоянно вылезает. Я так понимаю, что это из-за того, что ф-ция вне объекта находится.