David Mort
/
SPI_flex
CLASS for software SPI master class instantiated on any general IO pin. Slow but flexible.
SPI_flex.cpp
- Committer:
- dtmort
- Date:
- 2014-03-22
- Revision:
- 0:9e3e70548ec3
File content as of revision 0:9e3e70548ec3:
/* Class SPI_flex, Copyright 2014, David T. Mort (http://mbed.org/users/dtmort/) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "SPI_flex.h" #include "mbed.h" SPI_flex::SPI_flex(PinName mosi, PinName miso, PinName sclk, PinName cs): _mosi(mosi), _miso(miso), _sclk(sclk), _cs(cs) { _mosi=0; //initialize mosi pin _sclk=0; //initialize serial clock pin format(); //initialize hardware length & mode csactive(); //initialize chip select setup active state _cs=!__cs; //initialize chip select pin inactive } void SPI_flex::format(unsigned int bits, int mode){ BitString=bits; if (mode<4){_mode=mode;} //test if 0-3 _cpol= _mode & 0x02; //extract clock polarity (idle state) _cpha= _mode & 0x01; //extract clock phase (capture edge) } void SPI_flex::csactive(bool cs){ __cs=cs; } void SPI_flex::frequency(int Hz){ Dcpwi= (400000-Hz)/14260; //set Delay clock pulse width inactive Dcpwa= (400000-Hz)/14260; //set Delay clock pulse width active } void SPI_flex::select(void){ _deAssert=1; //initialze chip select bit counter if (_cpol) _sclk=1; else _sclk=0; //initialize sclk _cs=__cs; //assert chip select (SSEL) // wait_us(1); //Tcss CS to SCLK Setup Time (+Dcpwi) } bool SPI_flex::writebit(bool bit){ // int id=500, ad=500; int id=Dcpwi, ad=Dcpwa; //intialize frequency slowdown counters if (_cs!=__cs)select(); //assert cs auto-count sequence if not already engaged if (_cpha) {_sclk =!_sclk; //when 2nd clock edge capture (if CPHA=1) bit_read=_miso;} // read & store miso (if CPHA=1) if (bit) _mosi=1; else _mosi=0; //setup data on mosi while(id){__nop(); id--;} //Dcpwi Clock Pulse Width Inactive Delay (half period) _sclk =!_sclk; //toggle sclk (capture edge) while(ad){__nop(); ad--;} //Dcpwa Clock Pulse Width Active Delay (half period) _deAssert++; //advance chip select bit counter if (_deAssert > BitString){deSelect();};//call function to latch data (while clock still active) if (!_cpha) {_sclk =!_sclk; //when 1st clock edge capture (if CPHA=0) bit_read=_miso;} // read & store miso (if CPHA=0) return bit_read; } uint8_t SPI_flex::writebyte(uint8_t byte){ int mask=0x80; //set MSB mask position while (mask){ //MSB -> LSB (7:0) byte_read= mask &(writebit(byte & mask)); //write to mosi, read from miso mask>>=1;} //move mask one position right return byte_read; } uint16_t SPI_flex::writeword(uint16_t word){ int mask=0x8000; //set MSB mask position while (mask){ //MSB -> LSB (15:0) word_read= mask &(writebit(word & mask)); //write to mosi, read from miso mask>>=1;} //move mask one position right return word_read; } void SPI_flex::deSelect(void){ _cs=!__cs; //de-activate chip select while sclk is still active** on LSB while(0){__nop();} //Tcspi Chip Select Pulse Inactive Time _deAssert = 0; //reset chip select counter _mosi=0; //reset mosi }