2017-03-12 15 views
0

コードサイズとパフォーマンスが両立する組み込みデバイスドライバライブラリ(Arduino Mega)を作成しています。条件付きテンプレートを使用して関数を呼び出すC++

SPIコントローラは、移行操作の配列を有する:

  1. 選択SPIスレーブノード
  2. 転送データ
  3. 選択解除スレーブノード

選択/選択解除されているスタート/トランザクションの停止。これは、ピンをハイまたはローにすることによって行われます。 SPIスレーブノード回路は、標準の非反転デジタル信号(select ==高電圧、deselect == ground)または反転信号(select == ground、deselect == high voltage)を使用することができます。

select()は、ピンが反転されているかどうかをチェックするための実行時条件を使用して実装できます(次にclearPin()を発行するかしないか(setPin()を発行する)。同じことがdeselect()にも適用されます。 constsと静的な定義を使用すると、コンパイラはコンパイル時にで条件を解決できるはずです。コンパイラ(Avr-gcc 4.9)は、これらの式を減らす(インライン化する)ことができるとは必ずしも認識していません。だから、

、私はこのような条件付きテンプレートを使用しようとしているこの問題を回避するには:

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 
      } 
     }; 

選択()と(選択を解除)を同様に使用することができます:

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

すべてselect()/ deselect()は5つ以下のアセンブラ命令にコンパイルされます。しかし、構造体SelectPinのインスタンスを渡す方法の解決策は、関数のパラメータリストでテンプレート条件を指定する必要はありません。私は、テンプレートを使用せずに、反転と非反転セレクト・ピンのためのオーバーロードされた関数を書かれている可能性がありますので

// 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; 
     } 

:私は機能で選択・転送・選択解除を包むたい場合は言い換えれば、私は次のことを行う必要があり私は基本的に正方形に戻っています。

私は本質的に基本テンプレートを1つの関数定義のパラメータとして使用できるようにする方法がありますか?線に沿って何か:

// 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; 
     } 

はい、私は2つのオーバーロードされた関数は、すぐに仕事をするだろうと実感が、私は、これは私のcrapy選択ピンのほかに、一般的な意味を持っていることを感じています。

答えて

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

関連する問題