CLASS for software SPI master class instantiated on any general IO pin. Slow but flexible.

Dependencies:   mbed

Committer:
dtmort
Date:
Sat Mar 22 18:53:40 2014 +0000
Revision:
0:9e3e70548ec3
Initial commit 2014.03.22

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dtmort 0:9e3e70548ec3 1 /* Class SPI_flex, Copyright 2014, David T. Mort (http://mbed.org/users/dtmort/)
dtmort 0:9e3e70548ec3 2
dtmort 0:9e3e70548ec3 3 Licensed under the Apache License, Version 2.0 (the "License");
dtmort 0:9e3e70548ec3 4 you may not use this file except in compliance with the License.
dtmort 0:9e3e70548ec3 5 You may obtain a copy of the License at
dtmort 0:9e3e70548ec3 6
dtmort 0:9e3e70548ec3 7 http://www.apache.org/licenses/LICENSE-2.0
dtmort 0:9e3e70548ec3 8
dtmort 0:9e3e70548ec3 9 Unless required by applicable law or agreed to in writing, software
dtmort 0:9e3e70548ec3 10 distributed under the License is distributed on an "AS IS" BASIS,
dtmort 0:9e3e70548ec3 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dtmort 0:9e3e70548ec3 12 See the License for the specific language governing permissions and
dtmort 0:9e3e70548ec3 13 limitations under the License.
dtmort 0:9e3e70548ec3 14 */
dtmort 0:9e3e70548ec3 15 #include "SPI_flex.h"
dtmort 0:9e3e70548ec3 16 #include "mbed.h"
dtmort 0:9e3e70548ec3 17
dtmort 0:9e3e70548ec3 18 SPI_flex::SPI_flex(PinName mosi, PinName miso, PinName sclk, PinName cs):
dtmort 0:9e3e70548ec3 19 _mosi(mosi), _miso(miso), _sclk(sclk), _cs(cs) {
dtmort 0:9e3e70548ec3 20 _mosi=0; //initialize mosi pin
dtmort 0:9e3e70548ec3 21 _sclk=0; //initialize serial clock pin
dtmort 0:9e3e70548ec3 22 format(); //initialize hardware length & mode
dtmort 0:9e3e70548ec3 23 csactive(); //initialize chip select setup active state
dtmort 0:9e3e70548ec3 24 _cs=!__cs; //initialize chip select pin inactive
dtmort 0:9e3e70548ec3 25 }
dtmort 0:9e3e70548ec3 26
dtmort 0:9e3e70548ec3 27 void SPI_flex::format(unsigned int bits, int mode){
dtmort 0:9e3e70548ec3 28 BitString=bits;
dtmort 0:9e3e70548ec3 29 if (mode<4){_mode=mode;} //test if 0-3
dtmort 0:9e3e70548ec3 30 _cpol= _mode & 0x02; //extract clock polarity (idle state)
dtmort 0:9e3e70548ec3 31 _cpha= _mode & 0x01; //extract clock phase (capture edge)
dtmort 0:9e3e70548ec3 32 }
dtmort 0:9e3e70548ec3 33
dtmort 0:9e3e70548ec3 34
dtmort 0:9e3e70548ec3 35 void SPI_flex::csactive(bool cs){
dtmort 0:9e3e70548ec3 36 __cs=cs;
dtmort 0:9e3e70548ec3 37 }
dtmort 0:9e3e70548ec3 38
dtmort 0:9e3e70548ec3 39 void SPI_flex::frequency(int Hz){
dtmort 0:9e3e70548ec3 40 Dcpwi= (400000-Hz)/14260; //set Delay clock pulse width inactive
dtmort 0:9e3e70548ec3 41 Dcpwa= (400000-Hz)/14260; //set Delay clock pulse width active
dtmort 0:9e3e70548ec3 42
dtmort 0:9e3e70548ec3 43 }
dtmort 0:9e3e70548ec3 44
dtmort 0:9e3e70548ec3 45 void SPI_flex::select(void){
dtmort 0:9e3e70548ec3 46 _deAssert=1; //initialze chip select bit counter
dtmort 0:9e3e70548ec3 47 if (_cpol) _sclk=1; else _sclk=0; //initialize sclk
dtmort 0:9e3e70548ec3 48 _cs=__cs; //assert chip select (SSEL)
dtmort 0:9e3e70548ec3 49 // wait_us(1); //Tcss CS to SCLK Setup Time (+Dcpwi)
dtmort 0:9e3e70548ec3 50 }
dtmort 0:9e3e70548ec3 51
dtmort 0:9e3e70548ec3 52 bool SPI_flex::writebit(bool bit){
dtmort 0:9e3e70548ec3 53 // int id=500, ad=500;
dtmort 0:9e3e70548ec3 54 int id=Dcpwi, ad=Dcpwa; //intialize frequency slowdown counters
dtmort 0:9e3e70548ec3 55 if (_cs!=__cs)select(); //assert cs auto-count sequence if not already engaged
dtmort 0:9e3e70548ec3 56 if (_cpha) {_sclk =!_sclk; //when 2nd clock edge capture (if CPHA=1)
dtmort 0:9e3e70548ec3 57 bit_read=_miso;} // read & store miso (if CPHA=1)
dtmort 0:9e3e70548ec3 58 if (bit) _mosi=1; else _mosi=0; //setup data on mosi
dtmort 0:9e3e70548ec3 59 while(id){__nop(); id--;} //Dcpwi Clock Pulse Width Inactive Delay (half period)
dtmort 0:9e3e70548ec3 60 _sclk =!_sclk; //toggle sclk (capture edge)
dtmort 0:9e3e70548ec3 61 while(ad){__nop(); ad--;} //Dcpwa Clock Pulse Width Active Delay (half period)
dtmort 0:9e3e70548ec3 62 _deAssert++; //advance chip select bit counter
dtmort 0:9e3e70548ec3 63 if (_deAssert > BitString){deSelect();};//call function to latch data (while clock still active)
dtmort 0:9e3e70548ec3 64 if (!_cpha) {_sclk =!_sclk; //when 1st clock edge capture (if CPHA=0)
dtmort 0:9e3e70548ec3 65 bit_read=_miso;} // read & store miso (if CPHA=0)
dtmort 0:9e3e70548ec3 66 return bit_read;
dtmort 0:9e3e70548ec3 67 }
dtmort 0:9e3e70548ec3 68
dtmort 0:9e3e70548ec3 69 uint8_t SPI_flex::writebyte(uint8_t byte){
dtmort 0:9e3e70548ec3 70 int mask=0x80; //set MSB mask position
dtmort 0:9e3e70548ec3 71 while (mask){ //MSB -> LSB (7:0)
dtmort 0:9e3e70548ec3 72 byte_read= mask &(writebit(byte & mask)); //write to mosi, read from miso
dtmort 0:9e3e70548ec3 73 mask>>=1;} //move mask one position right
dtmort 0:9e3e70548ec3 74 return byte_read;
dtmort 0:9e3e70548ec3 75 }
dtmort 0:9e3e70548ec3 76
dtmort 0:9e3e70548ec3 77 uint16_t SPI_flex::writeword(uint16_t word){
dtmort 0:9e3e70548ec3 78 int mask=0x8000; //set MSB mask position
dtmort 0:9e3e70548ec3 79 while (mask){ //MSB -> LSB (15:0)
dtmort 0:9e3e70548ec3 80 word_read= mask &(writebit(word & mask)); //write to mosi, read from miso
dtmort 0:9e3e70548ec3 81 mask>>=1;} //move mask one position right
dtmort 0:9e3e70548ec3 82 return word_read;
dtmort 0:9e3e70548ec3 83 }
dtmort 0:9e3e70548ec3 84
dtmort 0:9e3e70548ec3 85
dtmort 0:9e3e70548ec3 86
dtmort 0:9e3e70548ec3 87
dtmort 0:9e3e70548ec3 88 void SPI_flex::deSelect(void){
dtmort 0:9e3e70548ec3 89 _cs=!__cs; //de-activate chip select while sclk is still active** on LSB
dtmort 0:9e3e70548ec3 90 while(0){__nop();} //Tcspi Chip Select Pulse Inactive Time
dtmort 0:9e3e70548ec3 91 _deAssert = 0; //reset chip select counter
dtmort 0:9e3e70548ec3 92 _mosi=0; //reset mosi
dtmort 0:9e3e70548ec3 93 }