Skip to content

Commit

Permalink
first working version
Browse files Browse the repository at this point in the history
  • Loading branch information
xxxajk committed Nov 21, 2013
1 parent f3af7b2 commit ae5d722
Show file tree
Hide file tree
Showing 2 changed files with 239 additions and 0 deletions.
198 changes: 198 additions & 0 deletions spi4teensy3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
* File: spi4teensy3.cpp
* Author: xxxajk
*
* Created on November 21, 2013, 10:54 AM
*/

#ifdef __MK20DX128__
#include "spi4teensy3.h"

namespace spi4teensy3 {
uint32_t ctar0;
uint32_t ctar1;

// Generic init. Maximum speed, cpol and cpha 0.

void init() {
SIM_SCGC6 |= SIM_SCGC6_SPI0;
CORE_PIN11_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
CORE_PIN12_CONFIG = PORT_PCR_MUX(2);
CORE_PIN13_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);

ctar0 = SPI_CTAR_DBR | SPI_CTAR_FMSZ(7);
ctar1 = SPI_CTAR_DBR | SPI_CTAR_FMSZ(15);
SPI0_MCR = SPI_MCR_MSTR;
SPI0_MCR |= SPI_MCR_CLR_RXF | SPI_MCR_CLR_TXF;
updatectars();
}

// init full speed, with cpol and cpha configurable.

void init(uint8_t cpol, uint8_t cpha) {
init();
ctar0 |= (cpol == 0 ? 0 : SPI_CTAR_CPOL) | (cpha == 0 ? 0 : SPI_CTAR_CPHA);
ctar1 |= (cpol == 0 ? 0 : SPI_CTAR_CPOL) | (cpha == 0 ? 0 : SPI_CTAR_CPHA);
updatectars();
}

// init with speed, cpol and cpha 0.

void init(uint8_t speed) {
init();
// Default 1/2 speed
uint32_t ctar = SPI_CTAR_DBR;
switch (speed) {
case 1: // 1/4
ctar = 0;
break;
case 2: // 1/8
ctar = SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);

break;
case 3: // 1/12
ctar = SPI_CTAR_BR(2) | SPI_CTAR_CSSCK(2);
break;

case 4: // 1/16
ctar = SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(3);
break;

case 5: // 1/32
ctar = SPI_CTAR_PBR(1) | SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(4);
break;

case 6: // 1/64
ctar = SPI_CTAR_PBR(1) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(5);
break;

case 7: //1/128
ctar = SPI_CTAR_PBR(1) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(6);
// fall thru
default:
// default 1/2 speed, this is the maximum.
break;
}
ctar0 = ctar | SPI_CTAR_FMSZ(7);
ctar1 = ctar | SPI_CTAR_FMSZ(15);
updatectars();
}

void init(uint8_t speed, uint8_t cpol, uint8_t cpha) {
init(speed);
ctar0 |= (cpol == 0 ? 0 : SPI_CTAR_CPOL) | (cpha == 0 ? 0 : SPI_CTAR_CPHA);
ctar1 |= (cpol == 0 ? 0 : SPI_CTAR_CPOL) | (cpha == 0 ? 0 : SPI_CTAR_CPHA);
updatectars();
}

void updatectars() {
uint32_t mcr = SPI0_MCR;
if (mcr & SPI_MCR_MDIS) {
SPI0_CTAR0 = ctar0;
SPI0_CTAR1 = ctar1;
} else {
SPI0_MCR = mcr | SPI_MCR_MDIS | SPI_MCR_HALT;
SPI0_CTAR0 = ctar0;
SPI0_CTAR1 = ctar1;
SPI0_MCR = mcr;
}
}

// sends 1 byte

void send(uint8_t b) {
SPI0_MCR |= SPI_MCR_CLR_RXF;
SPI0_SR = SPI_SR_TCF;
SPI0_PUSHR = b;
while (!(SPI0_SR & SPI_SR_TCF));

}

// sends > 1 byte from an array

void send(void *bufr, size_t n) {
int i;
int nf;
uint8_t *buf = (uint8_t *)bufr;
// clear any data in TX FIFO
SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_CLR_TXF;
//SPI0_MCR |= SPI_MCR_CLR_RXF | SPI_MCR_CLR_TXF;
if (n & 1) {
send(*buf++);
n--;
}
// initial number of words to push into TX FIFO
nf = n / 2 < 3 ? n / 2 : 3;
// limit for pushing data into TX fifo
uint8_t* limit = buf + n;
for (i = 0; i < nf; i++) {
uint16_t w = (*buf++) << 8;
w |= *buf++;
SPI0_PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | w;
}
// write data to TX FIFO
while (buf < limit) {
uint16_t w = *buf++ << 8;
w |= *buf++;
while (!(SPI0_SR & SPI_SR_RXCTR));
SPI0_PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | w;
SPI0_POPR;
}
// wait for data to be sent
while (nf) {
while (!(SPI0_SR & SPI_SR_RXCTR));
SPI0_POPR;
nf--;
}
}

// receive 1 byte

uint8_t receive() {
SPI0_MCR |= SPI_MCR_CLR_RXF;
SPI0_SR = SPI_SR_TCF;
SPI0_PUSHR = 0xFF;
while (!(SPI0_SR & SPI_SR_TCF));
return SPI0_POPR;
}

// receive many bytes into an array

void receive(void *bufr, size_t n) {
int i;
uint8_t *buf = (uint8_t *)bufr;
// clear any data in RX FIFO
//SPI0_MCR |= SPI_MCR_CLR_RXF;
SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF;
if (n & 1) {
*buf++ = receive();
n--;
}
// initial number of words to push into TX FIFO
int nf = n / 2 < 3 ? n / 2 : 3;
for (i = 0; i < nf; i++) {
SPI0_PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | 0XFFFF;
}
uint8_t* limit = buf + n - 2 * nf;
while (buf < limit) {
while (!(SPI0_SR & SPI_SR_RXCTR)) {
}
SPI0_PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | 0XFFFF;
uint16_t w = SPI0_POPR;
*buf++ = w >> 8;
*buf++ = w & 0XFF;
}
// limit for rest of RX data
limit += 2 * nf;
while (buf < limit) {
while (!(SPI0_SR & SPI_SR_RXCTR)) {
}
uint16_t w = SPI0_POPR;
*buf++ = w >> 8;
*buf++ = w & 0XFF;
}

}
}
#endif

41 changes: 41 additions & 0 deletions spi4teensy3.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* File: spi4teensy3.h
* Author: xxxajk
*
* Created on November 21, 2013, 10:54 AM
*/

#ifndef SPI4TEENSY3_H
#define SPI4TEENSY3_H
#ifdef __MK20DX128__
#include <mk20dx128.h>
#include <core_pins.h>
#include <sys/types.h>

#ifndef SPI_SR_RXCTR
#define SPI_SR_RXCTR 0XF0
#endif
#ifndef SPI_PUSHR_CONT
#define SPI_PUSHR_CONT 0X80000000
#endif
#ifndef SPI_PUSHR_CTAS
#define SPI_PUSHR_CTAS(n) (((n) & 7) << 28)
#endif


namespace spi4teensy3 {
void init();
void init(uint8_t cpol, uint8_t cpha);
void send(uint8_t b);
void send(void *bufr, size_t n);
uint8_t receive();
void receive(void *bufr, size_t n);

// cached ctars for speed
//uint32_t ctar0;
//uint32_t ctar1;
void updatectars();
};
#endif /* __MK20DX128__ */
#endif /* SPI4TEENSY3_H */

0 comments on commit ae5d722

Please sign in to comment.