2017-07-18 18:29:06 -05:00
|
|
|
/**
|
|
|
|
* Marlin 3D Printer Firmware
|
|
|
|
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
|
|
|
*
|
|
|
|
* Based on Sprinter and grbl.
|
|
|
|
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Software SPI functions originally from Arduino Sd2Card Library
|
|
|
|
* Copyright (C) 2009 by William Greiman
|
2017-12-20 23:35:49 -06:00
|
|
|
*
|
|
|
|
* Completely rewritten and tuned by Eduardo José Tagle in 2017/2018
|
|
|
|
* in ARM thumb2 inline assembler and tuned for maximum speed and performance
|
|
|
|
* allowing SPI clocks of up to 12 Mhz to increase SD card read/write performance
|
2017-07-18 18:29:06 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Description: HAL for Arduino Due and compatible (SAM3X8E)
|
|
|
|
*
|
|
|
|
* For ARDUINO_ARCH_SAM
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef ARDUINO_ARCH_SAM
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// Includes
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
2017-09-06 06:28:32 -05:00
|
|
|
#include "../../inc/MarlinConfig.h"
|
2018-05-12 08:34:04 -05:00
|
|
|
#include "../Delay.h"
|
2017-07-18 18:29:06 -05:00
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// Public Variables
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// Public functions
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
2018-03-20 15:53:21 -05:00
|
|
|
#if ENABLED(DUE_SOFTWARE_SPI)
|
2018-03-10 22:46:32 -06:00
|
|
|
|
2017-07-18 18:29:06 -05:00
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// software SPI
|
|
|
|
// --------------------------------------------------------------------------
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
|
2018-05-12 08:34:04 -05:00
|
|
|
// Make sure GCC optimizes this file.
|
|
|
|
// Note that this line triggers a bug in GCC which is fixed by casting.
|
|
|
|
// See the note below.
|
2017-12-20 23:35:49 -06:00
|
|
|
#pragma GCC optimize (3)
|
|
|
|
|
2018-05-12 08:34:04 -05:00
|
|
|
typedef uint8_t (*pfnSpiTransfer)(uint8_t b);
|
2017-12-28 00:32:46 -06:00
|
|
|
typedef void (*pfnSpiRxBlock)(uint8_t* buf, uint32_t nbyte);
|
|
|
|
typedef void (*pfnSpiTxBlock)(const uint8_t* buf, uint32_t nbyte);
|
|
|
|
|
2017-12-20 23:35:49 -06:00
|
|
|
/* ---------------- Macros to be able to access definitions from asm */
|
|
|
|
#define _PORT(IO) DIO ## IO ## _WPORT
|
|
|
|
#define _PIN_MASK(IO) MASK(DIO ## IO ## _PIN)
|
|
|
|
#define _PIN_SHIFT(IO) DIO ## IO ## _PIN
|
|
|
|
#define PORT(IO) _PORT(IO)
|
|
|
|
#define PIN_MASK(IO) _PIN_MASK(IO)
|
|
|
|
#define PIN_SHIFT(IO) _PIN_SHIFT(IO)
|
|
|
|
|
|
|
|
// run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
|
|
|
|
static uint8_t spiTransferTx0(uint8_t bout) { // using Mode 0
|
|
|
|
register uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
|
|
|
|
register uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
|
|
|
|
register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
|
|
|
register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
2018-01-24 21:40:48 -06:00
|
|
|
register uint32_t idx = 0;
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Negate bout, as the assembler requires a negated value */
|
|
|
|
bout = ~bout;
|
|
|
|
|
|
|
|
/* The software SPI routine */
|
|
|
|
__asm__ __volatile__(
|
2018-05-11 00:27:36 -05:00
|
|
|
A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 7 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("ubfx %[idx],%[txval],#7,#1") /* Place bit 7 in bit 0 of idx*/
|
2017-12-20 23:35:49 -06:00
|
|
|
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#6,#1") /* Place bit 6 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 6 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#5,#1") /* Place bit 5 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 5 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#4,#1") /* Place bit 4 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 4 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#3,#1") /* Place bit 3 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 3 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#2,#1") /* Place bit 2 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 2 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#1,#1") /* Place bit 1 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 1 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[idx],%[txval],#0,#1") /* Place bit 0 in bit 0 of idx*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* Bit 0 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("nop") /* Result will be 0 */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
2017-12-28 00:32:46 -06:00
|
|
|
: [idx]"+r"( idx )
|
|
|
|
: [txval]"r"( bout ) ,
|
|
|
|
[mosi_mask]"r"( MOSI_MASK ),
|
|
|
|
[mosi_port]"r"( MOSI_PORT_PLUS30 ),
|
|
|
|
[sck_mask]"r"( SCK_MASK ),
|
|
|
|
[sck_port]"r"( SCK_PORT_PLUS30 )
|
2017-12-20 23:35:49 -06:00
|
|
|
: "cc"
|
|
|
|
);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-05-12 08:34:04 -05:00
|
|
|
// Calculates the bit band alias address and returns a pointer address to word.
|
|
|
|
// addr: The byte address of bitbanding bit.
|
|
|
|
// bit: The bit position of bitbanding bit.
|
|
|
|
#define BITBAND_ADDRESS(addr, bit) \
|
2017-12-28 00:32:46 -06:00
|
|
|
(((uint32_t)(addr) & 0xF0000000) + 0x02000000 + ((uint32_t)(addr)&0xFFFFF)*32 + (bit)*4)
|
|
|
|
|
2017-12-20 23:35:49 -06:00
|
|
|
// run at ~8 .. ~10Mhz - Rx version (Tx line not altered)
|
|
|
|
static uint8_t spiTransferRx0(uint8_t bout) { // using Mode 0
|
2018-01-24 21:40:48 -06:00
|
|
|
register uint32_t bin = 0;
|
|
|
|
register uint32_t work = 0;
|
2017-12-28 00:32:46 -06:00
|
|
|
register uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
|
2017-12-20 23:35:49 -06:00
|
|
|
register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
|
|
|
register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
|
|
|
UNUSED(bout);
|
|
|
|
|
|
|
|
/* The software SPI routine */
|
|
|
|
__asm__ __volatile__(
|
2018-05-11 00:27:36 -05:00
|
|
|
A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 7 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#7,#1") /* Store read bit as the bit 7 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 6 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#6,#1") /* Store read bit as the bit 6 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 5 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#5,#1") /* Store read bit as the bit 5 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 4 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#4,#1") /* Store read bit as the bit 4 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 3 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#3,#1") /* Store read bit as the bit 3 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 2 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#2,#1") /* Store read bit as the bit 2 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 1 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#1,#1") /* Store read bit as the bit 1 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
|
|
|
/* bit 0 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#0,#1") /* Store read bit as the bit 0 */
|
2017-12-20 23:35:49 -06:00
|
|
|
|
2017-12-28 00:32:46 -06:00
|
|
|
: [bin]"+r"(bin),
|
2017-12-20 23:35:49 -06:00
|
|
|
[work]"+r"(work)
|
2017-12-28 00:32:46 -06:00
|
|
|
: [bitband_miso_port]"r"( BITBAND_MISO_PORT ),
|
|
|
|
[sck_mask]"r"( SCK_MASK ),
|
|
|
|
[sck_port]"r"( SCK_PORT_PLUS30 )
|
2017-12-20 23:35:49 -06:00
|
|
|
: "cc"
|
|
|
|
);
|
|
|
|
|
2017-12-28 00:32:46 -06:00
|
|
|
return bin;
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// run at ~4Mhz
|
|
|
|
static uint8_t spiTransfer1(uint8_t b) { // using Mode 0
|
|
|
|
int bits = 8;
|
|
|
|
do {
|
|
|
|
WRITE(MOSI_PIN, b & 0x80);
|
2017-12-20 23:35:49 -06:00
|
|
|
b <<= 1; // little setup time
|
2017-07-18 18:29:06 -05:00
|
|
|
|
|
|
|
WRITE(SCK_PIN, HIGH);
|
2017-12-20 23:35:49 -06:00
|
|
|
DELAY_NS(125); // 10 cycles @ 84mhz
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
|
|
|
|
b |= (READ(MISO_PIN) != 0);
|
2017-07-18 18:29:06 -05:00
|
|
|
|
|
|
|
WRITE(SCK_PIN, LOW);
|
2017-12-20 23:35:49 -06:00
|
|
|
DELAY_NS(125); // 10 cycles @ 84mhz
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
} while (--bits);
|
2017-07-18 18:29:06 -05:00
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
// all the others
|
|
|
|
static uint32_t spiDelayCyclesX4 = (F_CPU/1000000); // 4uS => 125khz
|
|
|
|
|
|
|
|
static uint8_t spiTransferX(uint8_t b) { // using Mode 0
|
|
|
|
int bits = 8;
|
|
|
|
do {
|
|
|
|
WRITE(MOSI_PIN, b & 0x80);
|
|
|
|
b <<= 1; // little setup time
|
|
|
|
|
|
|
|
WRITE(SCK_PIN, HIGH);
|
|
|
|
__delay_4cycles(spiDelayCyclesX4);
|
|
|
|
|
|
|
|
b |= (READ(MISO_PIN) != 0);
|
|
|
|
|
|
|
|
WRITE(SCK_PIN, LOW);
|
|
|
|
__delay_4cycles(spiDelayCyclesX4);
|
|
|
|
} while (--bits);
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2017-12-28 00:32:46 -06:00
|
|
|
// Pointers to generic functions for byte transfers
|
2018-05-12 08:34:04 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Note: The cast is unnecessary, but without it, this file triggers a GCC 4.8.3-2014 bug.
|
|
|
|
* Later GCC versions do not have this problem, but at this time (May 2018) Arduino still
|
|
|
|
* uses that buggy and obsolete GCC version!!
|
|
|
|
*/
|
|
|
|
static pfnSpiTransfer spiTransferRx = (pfnSpiTransfer)spiTransferX;
|
|
|
|
static pfnSpiTransfer spiTransferTx = (pfnSpiTransfer)spiTransferX;
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
|
2017-12-28 00:32:46 -06:00
|
|
|
// Block transfers run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
|
|
|
|
static void spiTxBlock0(const uint8_t* ptr, uint32_t todo) {
|
|
|
|
register uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
|
|
|
|
register uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
|
|
|
|
register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
|
|
|
register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
2018-01-24 21:40:48 -06:00
|
|
|
register uint32_t work = 0;
|
|
|
|
register uint32_t txval = 0;
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* The software SPI routine */
|
|
|
|
__asm__ __volatile__(
|
2018-05-11 00:27:36 -05:00
|
|
|
A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax
|
2017-12-28 00:32:46 -06:00
|
|
|
|
2018-05-08 05:10:27 -05:00
|
|
|
L("loop%=")
|
|
|
|
A("ldrb.w %[txval], [%[ptr]], #1") /* Load value to send, increment buffer */
|
|
|
|
A("mvn %[txval],%[txval]") /* Negate value */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 7 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("ubfx %[work],%[txval],#7,#1") /* Place bit 7 in bit 0 of work*/
|
2017-12-28 00:32:46 -06:00
|
|
|
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#6,#1") /* Place bit 6 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 6 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#5,#1") /* Place bit 5 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 5 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#4,#1") /* Place bit 4 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 4 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#3,#1") /* Place bit 3 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 3 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#2,#1") /* Place bit 2 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 2 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#1,#1") /* Place bit 1 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 1 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ubfx %[work],%[txval],#0,#1") /* Place bit 0 in bit 0 of work*/
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* Bit 0 */
|
2018-05-12 08:34:04 -05:00
|
|
|
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("subs %[todo],#1") /* Decrement count of pending words to send, update status */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bne.n loop%=") /* Repeat until done */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
: [ptr]"+r" ( ptr ) ,
|
|
|
|
[todo]"+r" ( todo ) ,
|
|
|
|
[work]"+r"( work ) ,
|
|
|
|
[txval]"+r"( txval )
|
|
|
|
: [mosi_mask]"r"( MOSI_MASK ),
|
|
|
|
[mosi_port]"r"( MOSI_PORT_PLUS30 ),
|
|
|
|
[sck_mask]"r"( SCK_MASK ),
|
|
|
|
[sck_port]"r"( SCK_PORT_PLUS30 )
|
|
|
|
: "cc"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void spiRxBlock0(uint8_t* ptr, uint32_t todo) {
|
2018-01-24 21:40:48 -06:00
|
|
|
register uint32_t bin = 0;
|
|
|
|
register uint32_t work = 0;
|
2017-12-28 00:32:46 -06:00
|
|
|
register uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
|
|
|
|
register uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
|
|
|
|
register uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
|
|
|
|
|
|
|
|
/* The software SPI routine */
|
|
|
|
__asm__ __volatile__(
|
2018-05-11 00:27:36 -05:00
|
|
|
A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax
|
2017-12-28 00:32:46 -06:00
|
|
|
|
2018-05-08 05:10:27 -05:00
|
|
|
L("loop%=")
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 7 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#7,#1") /* Store read bit as the bit 7 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 6 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#6,#1") /* Store read bit as the bit 6 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 5 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#5,#1") /* Store read bit as the bit 5 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 4 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#4,#1") /* Store read bit as the bit 4 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 3 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#3,#1") /* Store read bit as the bit 3 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 2 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#2,#1") /* Store read bit as the bit 2 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 1 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#1,#1") /* Store read bit as the bit 1 */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
/* bit 0 */
|
2018-05-08 05:10:27 -05:00
|
|
|
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
|
|
|
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
|
|
|
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
|
|
|
A("bfi %[bin],%[work],#0,#1") /* Store read bit as the bit 0 */
|
|
|
|
|
|
|
|
A("subs %[todo],#1") /* Decrement count of pending words to send, update status */
|
|
|
|
A("strb.w %[bin], [%[ptr]], #1") /* Store read value into buffer, increment buffer pointer */
|
|
|
|
A("bne.n loop%=") /* Repeat until done */
|
2017-12-28 00:32:46 -06:00
|
|
|
|
|
|
|
: [ptr]"+r"(ptr),
|
|
|
|
[todo]"+r"(todo),
|
|
|
|
[bin]"+r"(bin),
|
|
|
|
[work]"+r"(work)
|
|
|
|
: [bitband_miso_port]"r"( BITBAND_MISO_PORT ),
|
|
|
|
[sck_mask]"r"( SCK_MASK ),
|
|
|
|
[sck_port]"r"( SCK_PORT_PLUS30 )
|
|
|
|
: "cc"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void spiTxBlockX(const uint8_t* buf, uint32_t todo) {
|
|
|
|
do {
|
|
|
|
(void) spiTransferTx(*buf++);
|
|
|
|
} while (--todo);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void spiRxBlockX(uint8_t* buf, uint32_t todo) {
|
|
|
|
do {
|
2018-04-04 20:13:27 -05:00
|
|
|
*buf++ = spiTransferRx(0xFF);
|
2017-12-28 00:32:46 -06:00
|
|
|
} while (--todo);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pointers to generic functions for block tranfers
|
2018-05-12 08:34:04 -05:00
|
|
|
static pfnSpiTxBlock spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
|
|
|
|
static pfnSpiRxBlock spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
|
2017-12-28 00:32:46 -06:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
#if MB(ALLIGATOR) // control SDSS pin
|
|
|
|
void spiBegin() {
|
|
|
|
SET_OUTPUT(SS_PIN);
|
|
|
|
WRITE(SS_PIN, HIGH);
|
|
|
|
SET_OUTPUT(SCK_PIN);
|
|
|
|
SET_INPUT(MISO_PIN);
|
|
|
|
SET_OUTPUT(MOSI_PIN);
|
|
|
|
}
|
2017-12-28 00:32:46 -06:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
uint8_t spiRec() {
|
|
|
|
WRITE(SS_PIN, LOW);
|
|
|
|
WRITE(MOSI_PIN, 1); /* Output 1s 1*/
|
|
|
|
uint8_t b = spiTransferRx(0xFF);
|
|
|
|
WRITE(SS_PIN, HIGH);
|
|
|
|
return b;
|
|
|
|
}
|
2018-03-05 10:51:09 -06:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
void spiRead(uint8_t* buf, uint16_t nbyte) {
|
|
|
|
uint32_t todo = nbyte;
|
|
|
|
if (todo == 0) return;
|
2018-03-05 10:51:09 -06:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
WRITE(SS_PIN, LOW);
|
|
|
|
WRITE(MOSI_PIN, 1); /* Output 1s 1*/
|
|
|
|
spiRxBlock(buf,nbyte);
|
|
|
|
WRITE(SS_PIN, HIGH);
|
|
|
|
}
|
2018-03-05 10:51:09 -06:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
void spiSend(uint8_t b) {
|
|
|
|
WRITE(SS_PIN, LOW);
|
|
|
|
(void) spiTransferTx(b);
|
|
|
|
WRITE(SS_PIN, HIGH);
|
|
|
|
}
|
2018-03-05 10:51:09 -06:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
|
|
|
WRITE(SS_PIN, LOW);
|
|
|
|
(void) spiTransferTx(token);
|
|
|
|
spiTxBlock(buf,512);
|
|
|
|
WRITE(SS_PIN, HIGH);
|
2018-03-11 10:28:46 -05:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
#else // let calling routine control SDSS
|
|
|
|
void spiBegin() {
|
|
|
|
SET_OUTPUT(SS_PIN);
|
|
|
|
SET_OUTPUT(SCK_PIN);
|
|
|
|
SET_INPUT(MISO_PIN);
|
|
|
|
SET_OUTPUT(MOSI_PIN);
|
|
|
|
}
|
2018-03-05 10:51:09 -06:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
uint8_t spiRec() {
|
|
|
|
WRITE(MOSI_PIN, 1); /* Output 1s 1*/
|
|
|
|
uint8_t b = spiTransferRx(0xFF);
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
void spiRead(uint8_t* buf, uint16_t nbyte) {
|
|
|
|
uint32_t todo = nbyte;
|
|
|
|
if (todo == 0) return;
|
|
|
|
|
|
|
|
WRITE(MOSI_PIN, 1); /* Output 1s 1*/
|
|
|
|
spiRxBlock(buf,nbyte);
|
|
|
|
}
|
|
|
|
|
|
|
|
void spiSend(uint8_t b) {
|
|
|
|
(void) spiTransferTx(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
|
|
|
(void) spiTransferTx(token);
|
|
|
|
spiTxBlock(buf,512);
|
|
|
|
|
|
|
|
#endif
|
2018-03-11 10:28:46 -05:00
|
|
|
|
2017-12-28 00:32:46 -06:00
|
|
|
}
|
|
|
|
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
/**
|
|
|
|
* spiRate should be
|
|
|
|
* 0 : 8 - 10 MHz
|
|
|
|
* 1 : 4 - 5 MHz
|
|
|
|
* 2 : 2 - 2.5 MHz
|
|
|
|
* 3 : 1 - 1.25 MHz
|
|
|
|
* 4 : 500 - 625 kHz
|
|
|
|
* 5 : 250 - 312 kHz
|
|
|
|
* 6 : 125 - 156 kHz
|
|
|
|
*/
|
2017-07-18 18:29:06 -05:00
|
|
|
void spiInit(uint8_t spiRate) {
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
switch (spiRate) {
|
|
|
|
case 0:
|
2018-05-12 08:34:04 -05:00
|
|
|
spiTransferTx = (pfnSpiTransfer)spiTransferTx0;
|
|
|
|
spiTransferRx = (pfnSpiTransfer)spiTransferRx0;
|
|
|
|
spiTxBlock = (pfnSpiTxBlock)spiTxBlock0;
|
|
|
|
spiRxBlock = (pfnSpiRxBlock)spiRxBlock0;
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
break;
|
|
|
|
case 1:
|
2018-05-12 08:34:04 -05:00
|
|
|
spiTransferTx = (pfnSpiTransfer)spiTransfer1;
|
|
|
|
spiTransferRx = (pfnSpiTransfer)spiTransfer1;
|
|
|
|
spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
|
|
|
|
spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
spiDelayCyclesX4 = (F_CPU/1000000) >> (6 - spiRate);
|
2018-05-12 08:34:04 -05:00
|
|
|
spiTransferTx = (pfnSpiTransfer)spiTransferX;
|
|
|
|
spiTransferRx = (pfnSpiTransfer)spiTransferX;
|
|
|
|
spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
|
|
|
|
spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
#if MB(ALLIGATOR)
|
|
|
|
WRITE(SS_PIN, HIGH);
|
2018-03-11 10:28:46 -05:00
|
|
|
#endif
|
2017-07-18 18:29:06 -05:00
|
|
|
WRITE(MOSI_PIN, HIGH);
|
|
|
|
WRITE(SCK_PIN, LOW);
|
|
|
|
}
|
|
|
|
|
2018-01-03 05:12:25 -06:00
|
|
|
/** Begin SPI transaction, set clock, bit order, data mode */
|
|
|
|
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
|
|
|
|
// TODO: to be implemented
|
2018-01-05 10:10:55 -06:00
|
|
|
}
|
|
|
|
|
Fixes for the Arduino DUE HAL (Serial Port, Graphics Display, EEPROM emulation) (#8651)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style cleanup (2)
* Style fixes (3)
* Fixing the DUE serial port assignments: Now -1 means the SAM3x USB Device emulating a serial port, and 0 means the USB to serial adapter included as a programming port
* Improving the Fast IO port access implementation on Arduino DUE
* Implemented EEPROM emulation on Due by storing data on the internal FLASH (with wear leveling)
* Implemented a Software SPI for the ST7920 graphics display for the Arduino RAMPS for DUE, as the default one in u8glib is clocking data too fast on ARM, and the display does not understand it.
* Fixing the case where the serial port selected is the USB device
* Adding configuration for the Makerparts 3D printer (www.makerparts.net)
* Tuned MakerParts acceleration on X and Y axis so it never loses steps. Also adjusted pulses per mm to match default hw configuration
* Fine tuned Maximum acceleration for MakerParts printer
* Style cleanup
* Style changes to u8g_dev_st7920_128_64_sw_spi.cpp
* Even more improvements to the FastIO HAL for DUE. Now WRITE() is 2 ASM instructions, if value is constant, and 5 cycles if value is not constant. Previously, it was 7..8 cycles
* After some problems and debugging, seems we need to align the interrupt vector table to 256 bytes, otherwise, the program sometimes stops working
* Moved comments out of macro, otherwise, token pasting does not properly work sometimes
* Improved Software SPI implementation on DUE: Now it honors the selected speed passed to spiInit(). This allows much faster SDCARD access, improving SDCARD menus and reducing latency
* Update u8g_dev_st7920_128_64_sw_spi.cpp
* Disabling EEPROM over FLASH emulatiion if an I2C or SPI EEPROM is present
2017-12-12 17:51:36 -06:00
|
|
|
#pragma GCC reset_options
|
|
|
|
|
2018-05-12 08:34:04 -05:00
|
|
|
#else // !SOFTWARE_SPI
|
2018-03-10 22:46:32 -06:00
|
|
|
|
2018-03-11 10:28:46 -05:00
|
|
|
#if MB(ALLIGATOR)
|
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
// slave selects controlled by SPI controller
|
|
|
|
// doesn't support changing SPI speeds for SD card
|
2018-03-11 10:28:46 -05:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// hardware SPI
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// 8.4 MHz, 4 MHz, 2 MHz, 1 MHz, 0.5 MHz, 0.329 MHz, 0.329 MHz
|
|
|
|
int spiDueDividors[] = { 10, 21, 42, 84, 168, 255, 255 };
|
|
|
|
bool spiInitMaded = false;
|
|
|
|
|
|
|
|
void spiBegin() {
|
2018-04-04 20:13:27 -05:00
|
|
|
if (spiInitMaded == false) {
|
2018-03-10 22:46:32 -06:00
|
|
|
// Configure SPI pins
|
|
|
|
PIO_Configure(
|
|
|
|
g_APinDescription[SCK_PIN].pPort,
|
|
|
|
g_APinDescription[SCK_PIN].ulPinType,
|
|
|
|
g_APinDescription[SCK_PIN].ulPin,
|
|
|
|
g_APinDescription[SCK_PIN].ulPinConfiguration);
|
|
|
|
PIO_Configure(
|
|
|
|
g_APinDescription[MOSI_PIN].pPort,
|
|
|
|
g_APinDescription[MOSI_PIN].ulPinType,
|
|
|
|
g_APinDescription[MOSI_PIN].ulPin,
|
|
|
|
g_APinDescription[MOSI_PIN].ulPinConfiguration);
|
|
|
|
PIO_Configure(
|
|
|
|
g_APinDescription[MISO_PIN].pPort,
|
|
|
|
g_APinDescription[MISO_PIN].ulPinType,
|
|
|
|
g_APinDescription[MISO_PIN].ulPin,
|
|
|
|
g_APinDescription[MISO_PIN].ulPinConfiguration);
|
|
|
|
|
|
|
|
// set master mode, peripheral select, fault detection
|
|
|
|
SPI_Configure(SPI0, ID_SPI0, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS);
|
|
|
|
SPI_Enable(SPI0);
|
|
|
|
|
|
|
|
#if MB(ALLIGATOR)
|
|
|
|
SET_OUTPUT(DAC0_SYNC);
|
|
|
|
#if EXTRUDERS > 1
|
|
|
|
SET_OUTPUT(DAC1_SYNC);
|
|
|
|
WRITE(DAC1_SYNC, HIGH);
|
|
|
|
#endif
|
|
|
|
SET_OUTPUT(SPI_EEPROM1_CS);
|
|
|
|
SET_OUTPUT(SPI_EEPROM2_CS);
|
|
|
|
SET_OUTPUT(SPI_FLASH_CS);
|
|
|
|
WRITE(DAC0_SYNC, HIGH);
|
|
|
|
WRITE(SPI_EEPROM1_CS, HIGH );
|
|
|
|
WRITE(SPI_EEPROM2_CS, HIGH );
|
|
|
|
WRITE(SPI_FLASH_CS, HIGH );
|
|
|
|
WRITE(SS_PIN, HIGH );
|
|
|
|
#endif // MB(ALLIGATOR)
|
2018-03-11 10:28:46 -05:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
OUT_WRITE(SDSS,0);
|
2018-03-11 10:28:46 -05:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
PIO_Configure(
|
|
|
|
g_APinDescription[SPI_PIN].pPort,
|
|
|
|
g_APinDescription[SPI_PIN].ulPinType,
|
|
|
|
g_APinDescription[SPI_PIN].ulPin,
|
|
|
|
g_APinDescription[SPI_PIN].ulPinConfiguration);
|
2018-03-11 10:28:46 -05:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
spiInit(1);
|
|
|
|
spiInitMaded = true;
|
|
|
|
}
|
2017-07-18 18:29:06 -05:00
|
|
|
}
|
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
void spiInit(uint8_t spiRate) {
|
2018-04-04 20:13:27 -05:00
|
|
|
if (spiInitMaded == false) {
|
|
|
|
if (spiRate > 6) spiRate = 1;
|
2018-03-10 22:46:32 -06:00
|
|
|
|
|
|
|
#if MB(ALLIGATOR)
|
|
|
|
// Set SPI mode 1, clock, select not active after transfer, with delay between transfers
|
|
|
|
SPI_ConfigureNPCS(SPI0, SPI_CHAN_DAC,
|
|
|
|
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDueDividors[spiRate]) |
|
|
|
|
SPI_CSR_DLYBCT(1));
|
|
|
|
// Set SPI mode 0, clock, select not active after transfer, with delay between transfers
|
|
|
|
SPI_ConfigureNPCS(SPI0, SPI_CHAN_EEPROM1, SPI_CSR_NCPHA |
|
|
|
|
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDueDividors[spiRate]) |
|
|
|
|
SPI_CSR_DLYBCT(1));
|
|
|
|
#endif//MB(ALLIGATOR)
|
2017-07-18 18:29:06 -05:00
|
|
|
|
2017-09-27 04:57:33 -05:00
|
|
|
// Set SPI mode 0, clock, select not active after transfer, with delay between transfers
|
2018-03-10 22:46:32 -06:00
|
|
|
SPI_ConfigureNPCS(SPI0, SPI_CHAN, SPI_CSR_NCPHA |
|
2017-07-18 18:29:06 -05:00
|
|
|
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDueDividors[spiRate]) |
|
|
|
|
SPI_CSR_DLYBCT(1));
|
2018-03-10 22:46:32 -06:00
|
|
|
SPI_Enable(SPI0);
|
|
|
|
spiInitMaded = true;
|
|
|
|
}
|
2017-07-18 18:29:06 -05:00
|
|
|
}
|
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
// Write single byte to SPI
|
|
|
|
void spiSend(byte b) {
|
|
|
|
// write byte with address and end transmission flag
|
|
|
|
SPI0->SPI_TDR = (uint32_t)b | SPI_PCS(SPI_CHAN) | SPI_TDR_LASTXFER;
|
|
|
|
// wait for transmit register empty
|
2017-07-18 18:29:06 -05:00
|
|
|
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
2018-03-10 22:46:32 -06:00
|
|
|
// wait for receive register
|
2017-07-18 18:29:06 -05:00
|
|
|
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
2018-03-10 22:46:32 -06:00
|
|
|
// clear status
|
2017-07-18 18:29:06 -05:00
|
|
|
SPI0->SPI_RDR;
|
2018-05-12 08:34:04 -05:00
|
|
|
//DELAY_US(1U);
|
2017-07-18 18:29:06 -05:00
|
|
|
}
|
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
void spiSend(const uint8_t* buf, size_t n) {
|
|
|
|
if (n == 0) return;
|
|
|
|
for (size_t i = 0; i < n - 1; i++) {
|
|
|
|
SPI0->SPI_TDR = (uint32_t)buf[i] | SPI_PCS(SPI_CHAN);
|
|
|
|
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
|
|
|
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
|
|
|
SPI0->SPI_RDR;
|
2018-05-12 08:34:04 -05:00
|
|
|
//DELAY_US(1U);
|
2018-03-10 22:46:32 -06:00
|
|
|
}
|
|
|
|
spiSend(buf[n - 1]);
|
|
|
|
}
|
2017-07-18 18:29:06 -05:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
void spiSend(uint32_t chan, byte b) {
|
|
|
|
uint8_t dummy_read = 0;
|
|
|
|
// wait for transmit register empty
|
2017-07-18 18:29:06 -05:00
|
|
|
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
2018-03-10 22:46:32 -06:00
|
|
|
// write byte with address and end transmission flag
|
|
|
|
SPI0->SPI_TDR = (uint32_t)b | SPI_PCS(chan) | SPI_TDR_LASTXFER;
|
|
|
|
// wait for receive register
|
2017-07-18 18:29:06 -05:00
|
|
|
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
2018-03-10 22:46:32 -06:00
|
|
|
// clear status
|
2017-07-18 18:29:06 -05:00
|
|
|
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 1)
|
|
|
|
dummy_read = SPI0->SPI_RDR;
|
|
|
|
UNUSED(dummy_read);
|
|
|
|
}
|
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
void spiSend(uint32_t chan, const uint8_t* buf, size_t n) {
|
|
|
|
uint8_t dummy_read = 0;
|
|
|
|
if (n == 0) return;
|
|
|
|
for (int i = 0; i < (int)n - 1; i++) {
|
|
|
|
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
|
|
|
SPI0->SPI_TDR = (uint32_t)buf[i] | SPI_PCS(chan);
|
|
|
|
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
|
|
|
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 1)
|
|
|
|
dummy_read = SPI0->SPI_RDR;
|
|
|
|
UNUSED(dummy_read);
|
|
|
|
}
|
|
|
|
spiSend(chan, buf[n - 1]);
|
|
|
|
}
|
2018-03-05 10:51:09 -06:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
// Read single byte from SPI
|
|
|
|
uint8_t spiRec() {
|
|
|
|
// write dummy byte with address and end transmission flag
|
|
|
|
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN) | SPI_TDR_LASTXFER;
|
|
|
|
// wait for transmit register empty
|
|
|
|
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
2018-03-05 10:51:09 -06:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
// wait for receive register
|
2017-07-18 18:29:06 -05:00
|
|
|
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
2018-03-10 22:46:32 -06:00
|
|
|
// get byte from receive register
|
2018-05-12 08:34:04 -05:00
|
|
|
//DELAY_US(1U);
|
2018-03-10 22:46:32 -06:00
|
|
|
return SPI0->SPI_RDR;
|
2018-03-05 10:51:09 -06:00
|
|
|
}
|
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
uint8_t spiRec(uint32_t chan) {
|
|
|
|
uint8_t spirec_tmp;
|
|
|
|
// wait for transmit register empty
|
2018-03-05 10:51:09 -06:00
|
|
|
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
2018-03-10 22:46:32 -06:00
|
|
|
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 1)
|
|
|
|
spirec_tmp = SPI0->SPI_RDR;
|
|
|
|
UNUSED(spirec_tmp);
|
|
|
|
|
|
|
|
// write dummy byte with address and end transmission flag
|
|
|
|
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(chan) | SPI_TDR_LASTXFER;
|
|
|
|
|
|
|
|
// wait for receive register
|
2018-03-05 10:51:09 -06:00
|
|
|
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
2018-03-10 22:46:32 -06:00
|
|
|
// get byte from receive register
|
|
|
|
return SPI0->SPI_RDR;
|
2018-03-05 10:51:09 -06:00
|
|
|
}
|
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
// Read from SPI into buffer
|
2018-04-04 20:13:27 -05:00
|
|
|
void spiRead(uint8_t* buf, uint16_t nbyte) {
|
2018-03-10 22:46:32 -06:00
|
|
|
if (nbyte-- == 0) return;
|
|
|
|
|
|
|
|
for (int i = 0; i < nbyte; i++) {
|
|
|
|
//while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
|
|
|
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN);
|
|
|
|
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
|
|
|
buf[i] = SPI0->SPI_RDR;
|
2018-05-12 08:34:04 -05:00
|
|
|
//DELAY_US(1U);
|
2018-03-10 22:46:32 -06:00
|
|
|
}
|
|
|
|
buf[nbyte] = spiRec();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write from buffer to SPI
|
|
|
|
void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
|
|
|
SPI0->SPI_TDR = (uint32_t)token | SPI_PCS(SPI_CHAN);
|
|
|
|
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
|
|
|
//while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
|
|
|
//SPI0->SPI_RDR;
|
|
|
|
for (int i = 0; i < 511; i++) {
|
|
|
|
SPI0->SPI_TDR = (uint32_t)buf[i] | SPI_PCS(SPI_CHAN);
|
|
|
|
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
|
|
|
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
|
|
|
SPI0->SPI_RDR;
|
2018-05-12 08:34:04 -05:00
|
|
|
//DELAY_US(1U);
|
2018-03-10 22:46:32 -06:00
|
|
|
}
|
|
|
|
spiSend(buf[511]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Begin SPI transaction, set clock, bit order, data mode */
|
|
|
|
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
|
|
|
|
// TODO: to be implemented
|
|
|
|
}
|
|
|
|
|
|
|
|
#else // U8G compatible hardware SPI
|
2018-03-11 10:28:46 -05:00
|
|
|
|
2018-03-23 09:37:58 -05:00
|
|
|
#define SPI_MODE_0_DUE_HW 2 // DUE CPHA control bit is inverted
|
|
|
|
#define SPI_MODE_1_DUE_HW 3
|
|
|
|
#define SPI_MODE_2_DUE_HW 0
|
|
|
|
#define SPI_MODE_3_DUE_HW 1
|
|
|
|
|
2018-04-04 20:13:27 -05:00
|
|
|
void spiInit(uint8_t spiRate=6) { // Default to slowest rate if not specified)
|
2018-03-10 22:46:32 -06:00
|
|
|
// 8.4 MHz, 4 MHz, 2 MHz, 1 MHz, 0.5 MHz, 0.329 MHz, 0.329 MHz
|
|
|
|
int spiDueDividors[] = { 10, 21, 42, 84, 168, 255, 255 };
|
2018-04-04 20:13:27 -05:00
|
|
|
if (spiRate > 6) spiRate = 1;
|
2018-03-10 22:46:32 -06:00
|
|
|
|
2018-04-04 20:13:27 -05:00
|
|
|
// Enable PIOA and SPI0
|
2018-03-10 22:46:32 -06:00
|
|
|
REG_PMC_PCER0 = (1UL << ID_PIOA) | (1UL << ID_SPI0);
|
|
|
|
|
2018-04-04 20:13:27 -05:00
|
|
|
// Disable PIO on A26 and A27
|
2018-05-08 09:17:44 -05:00
|
|
|
REG_PIOA_PDR = 0x0C000000;
|
2018-03-10 22:46:32 -06:00
|
|
|
OUT_WRITE(SDSS, 1);
|
|
|
|
|
2018-04-04 20:13:27 -05:00
|
|
|
// Reset SPI0 (from sam lib)
|
2018-03-10 22:46:32 -06:00
|
|
|
SPI0->SPI_CR = SPI_CR_SPIDIS;
|
|
|
|
SPI0->SPI_CR = SPI_CR_SWRST;
|
|
|
|
SPI0->SPI_CR = SPI_CR_SWRST;
|
|
|
|
SPI0->SPI_CR = SPI_CR_SPIEN;
|
|
|
|
|
2018-04-04 20:13:27 -05:00
|
|
|
// TMC2103 compatible setup
|
|
|
|
// Master mode, no fault detection, PCS bits in data written to TDR select CSR register
|
|
|
|
SPI0->SPI_MR = SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS;
|
|
|
|
// SPI mode 0, 8 Bit data transfer, baud rate
|
|
|
|
SPI0->SPI_CSR[3] = SPI_CSR_SCBR(spiDueDividors[spiRate]) | SPI_CSR_CSAAT | SPI_MODE_0_DUE_HW; // use same CSR as TMC2130
|
2018-03-11 10:28:46 -05:00
|
|
|
}
|
2018-03-10 22:46:32 -06:00
|
|
|
|
|
|
|
static uint8_t spiTransfer(uint8_t data) {
|
|
|
|
|
2018-04-04 20:13:27 -05:00
|
|
|
// Wait until tx register is empty
|
2018-03-10 22:46:32 -06:00
|
|
|
while( (SPI0->SPI_SR & SPI_SR_TDRE) == 0 );
|
2018-04-04 20:13:27 -05:00
|
|
|
// Send data
|
|
|
|
SPI0->SPI_TDR = (uint32_t)data | 0x00070000UL; // Add TMC2130 PCS bits to every byte
|
2018-03-10 22:46:32 -06:00
|
|
|
|
|
|
|
// wait for transmit register empty
|
|
|
|
while ((SPI0->SPI_SR & SPI_SR_TDRE) == 0);
|
|
|
|
|
|
|
|
// wait for receive register
|
|
|
|
while ((SPI0->SPI_SR & SPI_SR_RDRF) == 0);
|
|
|
|
// get byte from receive register
|
|
|
|
return SPI0->SPI_RDR;
|
|
|
|
}
|
|
|
|
|
|
|
|
void spiBegin() {
|
|
|
|
spiInit();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t spiRec() {
|
2018-04-04 20:13:27 -05:00
|
|
|
uint8_t data = spiTransfer(0xFF);
|
2018-03-10 22:46:32 -06:00
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2018-04-04 20:13:27 -05:00
|
|
|
void spiRead(uint8_t* buf, uint16_t nbyte) {
|
2018-03-10 22:46:32 -06:00
|
|
|
if (nbyte == 0) return;
|
2018-04-04 20:13:27 -05:00
|
|
|
for (int i = 0; i < nbyte; i++)
|
|
|
|
buf[i] = spiTransfer(0xFF);
|
2018-03-10 22:46:32 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void spiSend(uint8_t data) {
|
|
|
|
spiTransfer(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void spiSend(const uint8_t* buf, size_t n) {
|
|
|
|
if (n == 0) return;
|
|
|
|
for (uint16_t i = 0; i < n; i++)
|
|
|
|
spiTransfer(buf[i]);
|
|
|
|
}
|
2018-01-05 10:10:55 -06:00
|
|
|
|
2018-03-10 22:46:32 -06:00
|
|
|
void spiSendBlock(uint8_t token, const uint8_t* buf) {
|
|
|
|
spiTransfer(token);
|
|
|
|
for (uint16_t i = 0; i < 512; i++)
|
|
|
|
spiTransfer(buf[i]);
|
2018-03-11 10:28:46 -05:00
|
|
|
}
|
|
|
|
|
2018-05-12 08:34:04 -05:00
|
|
|
#endif // !ALLIGATOR
|
|
|
|
#endif // !SOFTWARE_SPI
|
2017-07-18 18:29:06 -05:00
|
|
|
|
|
|
|
#endif // ARDUINO_ARCH_SAM
|