Virtual SPI interface library. SPI専用ピンを使わず、通常のIOピンを使用してSPI通信を偽装します。 使い方は通常のSPIと同じようなものですが、frequency(周波数)の設定があまり厳密ではないので実験用途でデバッグしたいとき等にご使用ください。 「SPI専用のピンが壊れているのではないのか?」というときの確認に便利です。 Implement the SPI communication in the "only general purpose IO pin" without a SPI pin.

Dependents:   VirtualSPI

VSPI.cpp

Committer:
Yajirushi
Date:
2015-05-30
Revision:
0:1d153d73d37d

File content as of revision 0:1d153d73d37d:

#include "VSPI.h"

VSPI::VSPI(PinName mosi, PinName sclk){
    hasInput = false;
    hasSelect = false;
    VSPI(mosi, NC, sclk, NC);
}

VSPI::VSPI(PinName mosi, PinName miso, PinName sclk){
    hasSelect = false;
    VSPI(mosi, miso, sclk, NC);
}

VSPI::VSPI(PinName mosi, PinName miso, PinName sclk, PinName csel){
    mo = new DigitalOut(mosi);
    mi = new DigitalIn(miso);
    cl = new DigitalOut(sclk);
    cs = new DigitalOut(csel);

    hasInput = !(miso == NC);
    hasSelect = !(csel == NC);

    freq = 1000000;
    w_us = 1;
    mode = 0;
    bits = 8;
    activeLow = true;
    msbf = true;
    isHigh = false;
}

void VSPI::format(unsigned char bits, unsigned char mode){
    bits = (bits > 32)? 32:(bits<8)? 8:bits;
    mode = (mode > 4)? 0:mode;
    this->bits = bits;
    this->mode = mode;
}

void VSPI::frequency(unsigned int hz){
    freq = (hz>1000000)? 1000000:(hz<10000)? 10000:hz;
    w_us = (unsigned int)(1000000/(freq*2));
}

int VSPI::write(int value){
    int rv = 0;

    if(msbf) value = __rbit(value)>>(32 - bits);
    /*
    if(msbf){
        value = ((value&0xAAAAAAAA)>>1) | ((value&0x55555555)<<1);
        value = ((value&0xCCCCCCCC)>>2) | ((value&0x33333333)<<2);
        value = ((value&0xF0F0F0F0)>>4) | ((value&0x0F0F0F0F)<<4);
        value = ((value&0xFF00FF00)>>8) | ((value&0x00FF00FF)<<8);
        value = ((value&0xFFFF0000)>>16) | ((value&0x0000FFFF)<<16);
        value >>= (32 - bits);
    }
    */

    switch(mode){
        case 0: //CPOL=0 CPHA=0
            for(unsigned char i=0; i<bits; i++){
                mo->write((value>>i)&1);
                rv |= mi->read();
                wait_us(w_us);
                cl->write(1);
                wait_us(w_us);
                cl->write(0);
            }
            break;

        case 1: //CPOL=0 CPHA=1
            for(unsigned char i=0; i<bits; i++){
                cl->write(1);
                mo->write((value>>i)&1);
                rv |= mi->read();
                wait_us(w_us);
                cl->write(0);
                wait_us(w_us);
            }
            break;

        case 2: //CPOL=1 CPHA=0
            for(unsigned char i=0; i<bits; i++){
                mo->write((value>>i)&1);
                rv |= mi->read();
                wait_us(w_us);
                cl->write(0);
                wait_us(w_us);
                cl->write(1);
            }
            break;

        case 3: //CPOL=1 CPHA=1
            for(unsigned char i=0; i<bits; i++){
                cl->write(0);
                mo->write((value>>i)&1);
                rv |= mi->read();
                wait_us(w_us);
                cl->write(1);
                wait_us(w_us);
            }
            break;
    }

    if(!msbf) rv = __rbit(rv<<(32 - bits));
    /*
    if(hasInput && !msbf){
        rv <<= (32 - bits);
        rv = ((rv&0xAAAAAAAA)>>1) | ((rv&0x55555555)<<1);
        rv = ((rv&0xCCCCCCCC)>>2) | ((rv&0x33333333)<<2);
        rv = ((rv&0xF0F0F0F0)>>4) | ((rv&0x0F0F0F0F)<<4);
        rv = ((rv&0xFF00FF00)>>8) | ((rv&0x00FF00FF)<<8);
        rv = ((rv&0xFFFF0000)>>16) | ((rv&0x0000FFFF)<<16);
    }
    */

    return rv;
}

int VSPI::wwcs(int value){
    if(!hasSelect) return 0;

    cs->write(activeLow? 0:1);
    wait_us(w_us);

    int rv = write(value);

    wait_us(w_us);
    cs->write(activeLow? 1:0);
    isHigh = activeLow? 1:0;

    return rv;
}

int VSPI::wwcs(int value, unsigned int waitMicros){
    if(!hasSelect) return 0;

    cs->write(activeLow? 0:1);
    wait_us(waitMicros);

    int rv = write(value);

    wait_us(waitMicros);
    cs->write(activeLow? 1:0);
    isHigh = activeLow? 1:0;

    return rv;
}

void VSPI::setBitOrder(bool isMSBfirst){
    msbf = isMSBfirst;
}

void VSPI::setCSmode(bool isActiveLow){
    activeLow = isActiveLow;
    cs->write(activeLow? 1:0);
    isHigh = activeLow? 1:0;
}

void VSPI::setCS(bool H){
    cs->write(H? 1:0);
    isHigh = H;
}

bool VSPI::getCS(){
    return isHigh;
}

bool VSPI::csInvert(){
    cs->write(isHigh? 0:1);
    isHigh = !isHigh;
    return isHigh? 0:1;
}