|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- /* Teensyduino Core Library
- * http://www.pjrc.com/teensy/
- * Copyright (c) 2019 PJRC.COM, LLC.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * 1. The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * 2. If the Software is incorporated into a build system that allows
- * selection among a list of target devices, then similar target
- * devices manufactured by PJRC.COM must be included in the list of
- * target devices and selectable in the same manner.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
- #ifndef _avr_emulation_h_
- #define _avr_emulation_h_
-
- #include "imxrt.h"
- #include "core_pins.h"
- #include "pins_arduino.h"
-
- #ifdef __cplusplus
-
-
-
- // SPI Control Register SPCR
- #define SPIE 7 // SPI Interrupt Enable - not supported
- #define SPE 6 // SPI Enable
- #define DORD 5 // DORD: Data Order
- #define MSTR 4 // MSTR: Master/Slave Select
- #define CPOL 3 // CPOL: Clock Polarity
- #define CPHA 2 // CPHA: Clock Phase
- #define SPR1 1 // Clock: 3 = 125 kHz, 2 = 250 kHz, 1 = 1 MHz, 0->4 MHz
- #define SPR0 0
- // SPI Status Register SPSR
- #define SPIF 7 // SPIF: SPI Interrupt Flag
- #define WCOL 6 // WCOL: Write COLlision Flag - not implemented
- #define SPI2X 0 // SPI2X: Double SPI Speed Bit
- // SPI Data Register SPDR
-
-
- class SPCRemulation;
- class SPSRemulation;
- class SPDRemulation;
-
- class SPCRemulation
- {
- public:
- inline SPCRemulation & operator = (int val) __attribute__((always_inline)) {
- /*
- uint32_t ctar, mcr, sim6;
- //serial_print("SPCR=");
- //serial_phex(val);
- //serial_print("\n");
- sim6 = SIM_SCGC6;
- if (!(sim6 & SIM_SCGC6_SPI0)) {
- //serial_print("init1\n");
- SIM_SCGC6 = sim6 | SIM_SCGC6_SPI0;
- SPI0_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
- }
- if (!(val & (1<<SPE))) {
- SPI0_MCR |= SPI_MCR_MDIS; // TODO: use bitband for atomic access
- }
- ctar = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1);
- if (val & (1<<DORD)) ctar |= SPI_CTAR_LSBFE;
- if (val & (1<<CPOL)) ctar |= SPI_CTAR_CPOL;
- if (val & (1<<CPHA)) {
- ctar |= SPI_CTAR_CPHA;
- if ((val & 3) == 0) {
- ctar |= SPI_CTAR_BR(1) | SPI_CTAR_ASC(1);
- } else if ((val & 3) == 1) {
- ctar |= SPI_CTAR_BR(4) | SPI_CTAR_ASC(4);
- } else if ((val & 3) == 2) {
- ctar |= SPI_CTAR_BR(6) | SPI_CTAR_ASC(6);
- } else {
- ctar |= SPI_CTAR_BR(7) | SPI_CTAR_ASC(7);
- }
- } else {
- if ((val & 3) == 0) {
- ctar |= SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
- } else if ((val & 3) == 1) {
- ctar |= SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(4);
- } else if ((val & 3) == 2) {
- ctar |= SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(6);
- } else {
- ctar |= SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(7);
- }
- }
- ctar |= (SPI0_CTAR0 & SPI_CTAR_DBR);
- update_ctar(ctar);
- mcr = SPI_MCR_DCONF(0) | SPI_MCR_PCSIS(0x1F);
- if (val & (1<<MSTR)) mcr |= SPI_MCR_MSTR;
- if (val & (1<<SPE)) {
- mcr &= ~(SPI_MCR_MDIS | SPI_MCR_HALT);
- SPI0_MCR = mcr;
- enable_pins();
- } else {
- mcr |= (SPI_MCR_MDIS | SPI_MCR_HALT);
- SPI0_MCR = mcr;
- disable_pins();
- }
- //serial_print("MCR:");
- //serial_phex32(SPI0_MCR);
- //serial_print(", CTAR0:");
- //serial_phex32(SPI0_CTAR0);
- //serial_print("\n");
- */
- return *this;
- }
- inline SPCRemulation & operator |= (int val) __attribute__((always_inline)) {
- /*
- uint32_t sim6;
- //serial_print("SPCR |= ");
- //serial_phex(val);
- //serial_print("\n");
- sim6 = SIM_SCGC6;
- if (!(sim6 & SIM_SCGC6_SPI0)) {
- //serial_print("init2\n");
- SIM_SCGC6 = sim6 | SIM_SCGC6_SPI0;
- SPI0_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(1) | SPI_CTAR_BR(1);
- }
- if (val & ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) {
- uint32_t ctar = SPI0_CTAR0;
- if (val & (1<<DORD)) ctar |= SPI_CTAR_LSBFE; // TODO: use bitband
- if (val & (1<<CPOL)) ctar |= SPI_CTAR_CPOL;
- if (val & (1<<CPHA) && !(ctar & SPI_CTAR_CPHA)) {
- ctar |= SPI_CTAR_CPHA;
- ctar &= 0xFFFF00FF;
- ctar |= SPI_CTAR_ASC(ctar & 15);
- }
- if ((val & 3) != 0) {
- uint32_t br = ctar & 15;
- uint32_t priorval;
- if (br <= 1) priorval = 0;
- else if (br <= 4) priorval = 1;
- else if (br <= 6) priorval = 2;
- else priorval = 3;
- uint32_t newval = priorval | (val & 3);
- if (newval != priorval) {
- if (newval == 0) br = 1;
- else if (newval == 0) br = 4;
- else if (newval == 0) br = 6;
- else br = 7;
- ctar &= 0xFFFF00F0; // clear BR, ASC, CSSCK
- if ((ctar & SPI_CTAR_CPHA)) {
- ctar |= SPI_CTAR_BR(br) | SPI_CTAR_ASC(br);
- } else {
- ctar |= SPI_CTAR_BR(br) | SPI_CTAR_CSSCK(br);
- }
- }
- }
- update_ctar(ctar);
- }
- if (val & (1<<MSTR)) SPI0_MCR |= SPI_MCR_MSTR;
- if (val & (1<<SPE)) {
- SPI0_MCR &= ~(SPI_MCR_MDIS | SPI_MCR_HALT);
- enable_pins();
- }
- //serial_print("MCR:");
- //serial_phex32(SPI0_MCR);
- //serial_print(", CTAR0:");
- //serial_phex32(SPI0_CTAR0);
- //serial_print("\n");
- */
- return *this;
- }
- inline SPCRemulation & operator &= (int val) __attribute__((always_inline)) {
- /*
- //serial_print("SPCR &= ");
- //serial_phex(val);
- //serial_print("\n");
- SIM_SCGC6 |= SIM_SCGC6_SPI0;
- if (!(val & (1<<SPE))) {
- SPI0_MCR |= (SPI_MCR_MDIS | SPI_MCR_HALT);
- disable_pins();
- }
- if ((val & ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) != ((1<<DORD)|(1<<CPOL)|(1<<CPHA)|3)) {
- uint32_t ctar = SPI0_CTAR0;
- if (!(val & (1<<DORD))) ctar &= ~SPI_CTAR_LSBFE; // TODO: use bitband
- if (!(val & (1<<CPOL))) ctar &= ~SPI_CTAR_CPOL;
- if (!(val & (1<<CPHA)) && (ctar & SPI_CTAR_CPHA)) {
- ctar &= ~SPI_CTAR_CPHA;
- ctar &= 0xFFFF00FF;
- ctar |= SPI_CTAR_CSSCK(ctar & 15);
- }
- if ((val & 3) != 3) {
- uint32_t br = ctar & 15;
- uint32_t priorval;
- if (br <= 1) priorval = 0;
- else if (br <= 4) priorval = 1;
- else if (br <= 6) priorval = 2;
- else priorval = 3;
- uint32_t newval = priorval & (val & 3);
- if (newval != priorval) {
- if (newval == 0) br = 1;
- else if (newval == 0) br = 4;
- else if (newval == 0) br = 6;
- else br = 7;
- ctar &= 0xFFFF00F0; // clear BR, ASC, CSSCK
- if ((ctar & SPI_CTAR_CPHA)) {
- ctar |= SPI_CTAR_BR(br) | SPI_CTAR_ASC(br);
- } else {
- ctar |= SPI_CTAR_BR(br) | SPI_CTAR_CSSCK(br);
- }
- }
- }
- update_ctar(ctar);
- }
- if (!(val & (1<<MSTR))) SPI0_MCR &= ~SPI_MCR_MSTR;
- */
- return *this;
- }
- inline int operator & (int val) const __attribute__((always_inline)) {
- int ret = 0;
- /*
- //serial_print("SPCR & ");
- //serial_phex(val);
- //serial_print("\n");
- SIM_SCGC6 |= SIM_SCGC6_SPI0;
- if ((val & (1<<DORD)) && (SPI0_CTAR0 & SPI_CTAR_LSBFE)) ret |= (1<<DORD);
- if ((val & (1<<CPOL)) && (SPI0_CTAR0 & SPI_CTAR_CPOL)) ret |= (1<<CPOL);
- if ((val & (1<<CPHA)) && (SPI0_CTAR0 & SPI_CTAR_CPHA)) ret |= (1<<CPHA);
- if ((val & 3) != 0) {
- uint32_t dbr = SPI0_CTAR0 & 15;
- uint32_t spr10;
- if (dbr <= 1) {
- spr10 = 0;
- } else if (dbr <= 4) {
- spr10 |= (1<<SPR0);
- } else if (dbr <= 6) {
- spr10 |= (1<<SPR1);
- } else {
- spr10 |= (1<<SPR1)|(1<<SPR0);
- }
- ret |= spr10 & (val & 3);
- }
- if (val & (1<<SPE) && (!(SPI0_MCR & SPI_MCR_MDIS))) ret |= (1<<SPE);
- if (val & (1<<MSTR) && (SPI0_MCR & SPI_MCR_MSTR)) ret |= (1<<MSTR);
- //serial_print("ret = ");
- //serial_phex(ret);
- //serial_print("\n");
- */
- return ret;
- }
- operator int () const __attribute__((always_inline)) {
- int ret = 0;
- /*
- if ((SIM_SCGC6 & SIM_SCGC6_SPI0)) {
- int ctar = SPI0_CTAR0;
- if (ctar & SPI_CTAR_LSBFE) ret |= (1<<DORD);
- if (ctar & SPI_CTAR_CPOL) ret |= (1<<CPOL);
- if (ctar & SPI_CTAR_CPHA) ret |= (1<<CPHA);
- ctar &= 15;
- if (ctar <= 1) {
- } else if (ctar <= 4) {
- ret |= (1<<SPR0);
- } else if (ctar <= 6) {
- ret |= (1<<SPR1);
- } else {
- ret |= (1<<SPR1)|(1<<SPR0);
- }
- int mcr = SPI0_MCR;
- if (!(mcr & SPI_MCR_MDIS)) ret |= (1<<SPE);
- if (mcr & SPI_MCR_MSTR) ret |= (1<<MSTR);
- }
- */
- return ret;
- }
- inline void setMOSI(uint8_t pin) __attribute__((always_inline)) {
- }
- inline void setMOSI_soft(uint8_t pin) __attribute__((always_inline)) {
- }
- inline void setMISO(uint8_t pin) __attribute__((always_inline)) {
- }
- inline void setSCK(uint8_t pin) __attribute__((always_inline)) {
- }
- friend class SPSRemulation;
- friend class SPIFIFOclass;
- private:
- static uint8_t pinout;
- public:
- inline void enable_pins(void) __attribute__((always_inline)) {
- //serial_print("enable_pins\n");
- }
- inline void disable_pins(void) __attribute__((always_inline)) {
- }
- };
- extern SPCRemulation SPCR;
-
-
- class SPSRemulation
- {
- public:
- inline SPSRemulation & operator = (int val) __attribute__((always_inline)) {
- //serial_print("SPSR=");
- //serial_phex(val);
- //serial_print("\n");
- /*
- uint32_t ctar = SPI0_CTAR0;
- if (val & (1<<SPI2X)) {
- ctar |= SPI_CTAR_DBR;
- } else {
- ctar &= ~SPI_CTAR_DBR;
- }
- SPCRemulation::update_ctar(ctar);
- //serial_print("MCR:");
- //serial_phex32(SPI0_MCR);
- //serial_print(", CTAR0:");
- //serial_phex32(SPI0_CTAR0);
- //serial_print("\n");
- */
- return *this;
- }
- inline SPSRemulation & operator |= (int val) __attribute__((always_inline)) {
- /*
- //serial_print("SPSR |= ");
- //serial_phex(val);
- //serial_print("\n");
- if (val & (1<<SPI2X)) SPCRemulation::update_ctar(SPI0_CTAR0 |= SPI_CTAR_DBR);
- */
- return *this;
- }
- inline SPSRemulation & operator &= (int val) __attribute__((always_inline)) {
- /*
- //serial_print("SPSR &= ");
- //serial_phex(val);
- //serial_print("\n");
- if (!(val & (1<<SPI2X))) SPCRemulation::update_ctar(SPI0_CTAR0 &= ~SPI_CTAR_DBR);
- */
- return *this;
- }
- inline int operator & (int val) const __attribute__((always_inline)) {
- int ret = 0;
- //serial_print("SPSR & ");
- //serial_phex(val);
- //serial_print("\n");
- // TODO: using SPI_SR_TCF isn't quite right. Control returns to the
- // caller after the final edge that captures data, which is 1/2 cycle
- // sooner than AVR returns. At 500 kHz and slower SPI, this can make
- // a difference when digitalWrite is used to manually control the CS
- // pin, and perhaps it could matter at high clocks if faster register
- // access is used? But does it really matter? Do any SPI chips in
- // practice really perform differently if CS negates early, after the
- // final bit is clocked, but before the end of the whole clock cycle?
- if ((val & (1<<SPIF)) && ((LPSPI4_RSR & LPSPI_RSR_RXEMPTY) == 0)) ret = (1<<SPIF);
- //if ((val & (1<<SPI2X)) && (SPI0_CTAR0 & SPI_CTAR_DBR)) ret |= (1<<SPI2X);
- //delayMicroseconds(50000);
- return ret;
- }
- operator int () const __attribute__((always_inline)) {
- int ret = 0;
- //serial_print("SPSR (int)\n");
- if ((LPSPI4_RSR & LPSPI_RSR_RXEMPTY) == 0) ret = (1<<SPIF);
- //if (SPI0_CTAR0 & SPI_CTAR_DBR) ret |= (1<<SPI2X);
- return ret;
- }
- };
- extern SPSRemulation SPSR;
-
- class SPDRemulation
- {
- public:
- inline SPDRemulation & operator = (int val) __attribute__((always_inline)) {
- //serial_print("SPDR = ");
- //serial_phex(val);
- //serial_print("\n");
- LPSPI4_CR = LPSPI_CR_RRF | LPSPI_CR_MEN; // Module enabled anc clear the receive.
- LPSPI4_TDR = (val & 255);
- return *this;
- }
- operator int () const __attribute__((always_inline)) {
- uint32_t val;
- val = LPSPI4_RDR & 255;
- return val;
- }
- };
- extern SPDRemulation SPDR;
-
-
- #endif // __cplusplus
-
- #endif
|