2017-03-12 2 views
0

코드 크기와 성능이 동시에 필요한 임베디드 장치 드라이버 라이브러리 (Arduino Mega)를 작성 중입니다.조건부 템플릿을 사용하여 함수 호출하기 C++

는 SPI 제어기는 이동 동작의 시퀀스를 가지고

  1. 선택 SPI 슬레이브 노드
  2. 데이터 전송
  3. 선택 해제 슬레이브 노드

셀렉트/셀렉트되어 시작/거래 중지. 이는 핀을 높게 또는 낮게 어서 실행됩니다. SPI 슬레이브 노드 회로는 표준 비 반전 디지털 신호 (select == high voltage, deselect == ground) 또는 inverted 신호 (select == ground, deselect == high voltage)를 사용할 수 있습니다.

select()는 핀이 반전되었는지 확인하기 위해 런타임 조건을 사용하여 구현 될 수 있습니다 (clearPin()을 발행하거나) (setPin()을 발행하십시오). deselect()도 마찬가지입니다. consts와 정적 정의를 사용하면 컴파일러 이 컴파일 할 때 조건을 풀 수 있어야합니다. 결과적으로 컴파일러 (Avr-gcc 4.9)는 이러한 표현식을 줄일 수 있다는 것을 항상 깨닫지 못합니다.

그래서,이 같은 조건 템플릿을 사용하기 위해 노력하고있어이 문제를 해결 얻을 :

// Uses digital pin # 33 as Select pin 
static struct SelectPin<SelectPinType::INVERTED> SpiSel 
    { 
    Pin::PIN_DIO_33 
    }; 
... 
SpiSel.select(); 
doTransfer(dataBuffer); 
SpiSel.deselect(); 

모든 :

enum class SelectPinType : const bool 
    { 
    STANDARD = false, 
    INVERTED = true 
    }; 

template <SelectPinType tInvertedSelect> 
    struct SelectPin; 

template<> 
    struct SelectPin<SelectPinType::INVERTED> 
     { 
     const Pin::IOPin &mChipSelectPin; 

     inline void select() const __attribute__((always_inline)) 
      { 
      Pin::clr(mChipSelectPin); // Select inverted pin 
      } 
     inline void deselect() const __attribute__((always_inline)) 
      { 
      Pin::set(mChipSelectPin); // Deselect inverted pin 
      } 
     }; 

template<> 
    struct SelectPin<SelectPinType::STANDARD> 
     { 
     const Pin::IOPin &mChipSelectPin; 

     inline void select() const __attribute__((always_inline)) 
      { 
      Pin::set(mChipSelectPin); // Select standard pin 
      } 
     inline void deselect() const __attribute__((always_inline)) 
      { 
      Pin::clr(mChipSelectPin); // Deselect standard pin 
      } 
     }; 

합니다 (선택을)과() 해제 다음처럼 사용할 수 있습니다 잘 작동하고 select()/deselect()는 5 개 미만의 어셈블러 명령어로 컴파일됩니다. 그러나 구조체 SelectPin의 인스턴스를 전달하는 방법에 대한 해결책을 찾을 수 없는데, 함수 매개 변수 목록에 템플릿 조건을 지정하지 않아도됩니다. 내가 함수에서 선택 - 전송 - 선택 해제를 wrapp하려는 경우 즉, 나는 다음을 수행해야합니다 :

내가 과부하 기능을 쓸 수도 있기 때문에
// Inverted select pin transaction 
inline void doTransaction(const SelectPin<SelectPinType::INVERTED> &fSelectPin, Spi::Transfer &fTransfer) 
     { 

     // Perform the SPI transaction 
     fSelectPin.select(); 
     doTransfer(fTransfer); 
     fSelectPin.deselect(); 

     // Done 
     return; 
     } 

// Non-inverted select pin transaction 
inline void doTransaction(const SelectPin<SelectPinType::STANDARD> &fSelectPin, Spi::Transfer &fTransfer) 
     { 

     // Perform the SPI transaction 
     fSelectPin.select(); 
     doTransfer(fTransfer); 
     fSelectPin.deselect(); 

     // Done 
     return; 
     } 

반전 및 템플릿을 사용하지 않고 선택 핀을 비는 반전 , 나는 기본적으로 제곱에 돌아 간다.

본질적으로 기본 템플릿을 단일 함수 정의의 매개 변수로 사용할 수 있도록 방법이 있습니까? 의 라인을 따라 뭔가 :

// Accept any condition for the SelectPin template 
inline void doTransaction(const SelectPin<SelectPinType::*> &fSelectPin, Spi::Transfer &fTransfer) 
     { 

     // Perform the SPI transaction 
     fSelectPin.select(); 
     doTransfer(fTransfer); 
     fSelectPin.deselect(); 

     // Done 
     return; 
     } 

예, 내가이 개 과부하 기능이 바로 일을 할 것이라는 점을 깨닫게하지만이 내 크레이프 선택 핀 이외의 일반적인 영향을 미칠 수 있다는 것을 생각합니다.

답변

1

당신이 원하는 구문은 다음과 같습니다

template <SelectPinType E> 
void doTransaction(const SelectPin<E> &fSelectPin, Spi::Transfer &fTransfer) 
{ 
    // Perform the SPI transaction 
    fSelectPin.select(); 
    doTransfer(fTransfer); 
    fSelectPin.deselect(); 
} 

또는 짧은,하지만 덜 제약 조건 : 많이

template <typename T> 
void doTransaction(const T& fSelectPin, Spi::Transfer &fTransfer) 
{ 
    // Perform the SPI transaction 
    fSelectPin.select(); 
    doTransfer(fTransfer); 
    fSelectPin.deselect(); 
} 
+0

감사합니다! 그 자리에서! – Nilsie