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
This commit is contained in:
parent
c555a214d2
commit
ac168a03c8
1034
Marlin/src/HAL/HAL_DUE/EepromEmulation_Due.cpp
Normal file
1034
Marlin/src/HAL/HAL_DUE/EepromEmulation_Due.cpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -43,13 +43,7 @@
|
|||
|
||||
#if SERIAL_PORT == -1
|
||||
#define MYSERIAL SerialUSB
|
||||
#elif SERIAL_PORT == 0
|
||||
#define MYSERIAL customizedSerial
|
||||
#elif SERIAL_PORT == 1
|
||||
#define MYSERIAL customizedSerial
|
||||
#elif SERIAL_PORT == 2
|
||||
#define MYSERIAL customizedSerial
|
||||
#elif SERIAL_PORT == 3
|
||||
#elif SERIAL_PORT >= 0 && SERIAL_PORT <= 4
|
||||
#define MYSERIAL customizedSerial
|
||||
#endif
|
||||
|
||||
|
|
|
@ -52,30 +52,123 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// software SPI
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/* ---------------- Delay Cycles routine -------------- */
|
||||
|
||||
/* https://blueprints.launchpad.net/gcc-arm-embedded/+spec/delay-cycles */
|
||||
|
||||
#define nop() __asm__ __volatile__("nop;\n\t":::)
|
||||
|
||||
FORCE_INLINE static void __delay_4cycles(uint32_t cy) { // +1 cycle
|
||||
#if ARCH_PIPELINE_RELOAD_CYCLES<2
|
||||
#define EXTRA_NOP_CYCLES "nop"
|
||||
#else
|
||||
#define EXTRA_NOP_CYCLES ""
|
||||
#endif
|
||||
|
||||
__asm__ __volatile__(
|
||||
".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
|
||||
|
||||
"loop%=:" "\n\t"
|
||||
" subs %[cnt],#1" "\n\t"
|
||||
EXTRA_NOP_CYCLES "\n\t"
|
||||
" bne loop%=" "\n\t"
|
||||
: [cnt]"+r"(cy) // output: +r means input+output
|
||||
: // input:
|
||||
: "cc" // clobbers:
|
||||
);
|
||||
}
|
||||
|
||||
FORCE_INLINE static void DELAY_CYCLES(uint32_t x) {
|
||||
|
||||
if (__builtin_constant_p(x)) {
|
||||
|
||||
#define MAXNOPS 4
|
||||
|
||||
if (x <= (MAXNOPS)) {
|
||||
switch(x) { case 4: nop(); case 3: nop(); case 2: nop(); case 1: nop(); }
|
||||
}
|
||||
else { // because of +1 cycle inside delay_4cycles
|
||||
const uint32_t rem = (x - 1) % (MAXNOPS);
|
||||
switch(rem) { case 3: nop(); case 2: nop(); case 1: nop(); }
|
||||
if ((x = (x - 1) / (MAXNOPS)))
|
||||
__delay_4cycles(x); // if need more then 4 nop loop is more optimal
|
||||
}
|
||||
}
|
||||
else
|
||||
__delay_4cycles(x / 4);
|
||||
}
|
||||
|
||||
/* ---------------- Delay in nanoseconds and in microseconds */
|
||||
|
||||
#define DELAY_NS(x) DELAY_CYCLES( (x) * (F_CPU/1000000) / 1000)
|
||||
|
||||
typedef uint8_t (*pfnSpiTransfer) (uint8_t b);
|
||||
|
||||
// bitbanging transfer
|
||||
// run at ~100KHz (necessary for init)
|
||||
static uint8_t spiTransfer(uint8_t b) { // using Mode 0
|
||||
for (int bits = 0; bits < 8; bits++) {
|
||||
if (b & 0x80) {
|
||||
WRITE(MOSI_PIN, HIGH);
|
||||
#define SWSPI_BIT_XFER(n) \
|
||||
WRITE(MOSI_PIN, bout & (1 << n)); \
|
||||
WRITE(SCK_PIN, HIGH); /* Sampling point */\
|
||||
/* (implicit by overhead) DELAY_NS(63); 5.3 cycles @ 84mhz */ \
|
||||
bin |= (READ(MISO_PIN) != 0) << n; \
|
||||
WRITE(SCK_PIN, LOW); /* Toggling point*/ \
|
||||
/* (implicit by overhead) DELAY_NS(63); 5.3 cycles @ 84mhz */
|
||||
|
||||
// run at ~8 .. ~10Mhz
|
||||
static uint8_t spiTransfer0(uint8_t bout) { // using Mode 0
|
||||
volatile uint8_t bin = 0; /* volatile to disable deferred processing */
|
||||
SWSPI_BIT_XFER(7);
|
||||
SWSPI_BIT_XFER(6);
|
||||
SWSPI_BIT_XFER(5);
|
||||
SWSPI_BIT_XFER(4);
|
||||
SWSPI_BIT_XFER(3);
|
||||
SWSPI_BIT_XFER(2);
|
||||
SWSPI_BIT_XFER(1);
|
||||
SWSPI_BIT_XFER(0);
|
||||
return bin;
|
||||
}
|
||||
else {
|
||||
WRITE(MOSI_PIN, LOW);
|
||||
}
|
||||
b <<= 1;
|
||||
|
||||
// run at ~4Mhz
|
||||
static uint8_t spiTransfer1(uint8_t b) { // using Mode 0
|
||||
int bits = 8;
|
||||
do {
|
||||
WRITE(MOSI_PIN, b & 0x80);
|
||||
b <<= 1; // little setup time
|
||||
|
||||
WRITE(SCK_PIN, HIGH);
|
||||
delayMicroseconds(5U);
|
||||
DELAY_NS(125); // 10 cycles @ 84mhz
|
||||
|
||||
b |= (READ(MISO_PIN) != 0);
|
||||
|
||||
if (READ(MISO_PIN)) {
|
||||
b |= 1;
|
||||
}
|
||||
WRITE(SCK_PIN, LOW);
|
||||
delayMicroseconds(5U);
|
||||
}
|
||||
DELAY_NS(125); // 10 cycles @ 84mhz
|
||||
} while (--bits);
|
||||
return b;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Use the generic one
|
||||
static pfnSpiTransfer spiTransfer = spiTransferX;
|
||||
|
||||
void spiBegin() {
|
||||
SET_OUTPUT(SS_PIN);
|
||||
WRITE(SS_PIN, HIGH);
|
||||
|
@ -84,8 +177,30 @@
|
|||
SET_OUTPUT(MOSI_PIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void spiInit(uint8_t spiRate) {
|
||||
UNUSED(spiRate);
|
||||
switch (spiRate) {
|
||||
case 0:
|
||||
spiTransfer = spiTransfer0;
|
||||
break;
|
||||
case 1:
|
||||
spiTransfer = spiTransfer1;
|
||||
break;
|
||||
default:
|
||||
spiDelayCyclesX4 = (F_CPU/1000000) >> (6 - spiRate);
|
||||
spiTransfer = spiTransferX;
|
||||
break;
|
||||
}
|
||||
|
||||
WRITE(SS_PIN, HIGH);
|
||||
WRITE(MOSI_PIN, HIGH);
|
||||
WRITE(SCK_PIN, LOW);
|
||||
|
@ -137,6 +252,9 @@
|
|||
UNUSED(response);
|
||||
WRITE(SS_PIN, HIGH);
|
||||
}
|
||||
|
||||
#pragma GCC reset_options
|
||||
|
||||
#else
|
||||
// --------------------------------------------------------------------------
|
||||
// hardware SPI
|
||||
|
|
|
@ -35,9 +35,11 @@
|
|||
#include "HAL_Due.h"
|
||||
#include "InterruptVectors_Due.h"
|
||||
|
||||
/* The relocated Exception/Interrupt Table - Must be aligned to 128bytes,
|
||||
as bits 0-6 on VTOR register are reserved and must be set to 0 */
|
||||
__attribute__ ((aligned(128)))
|
||||
/* The relocated Exception/Interrupt Table - According to the ARM
|
||||
reference manual, alignment to 128 bytes should suffice, but in
|
||||
practice, we need alignment to 256 bytes to make this work in all
|
||||
cases */
|
||||
__attribute__ ((aligned(256)))
|
||||
static DeviceVectors ram_tab = { NULL };
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,48 +33,51 @@
|
|||
#include "InterruptVectors_Due.h"
|
||||
#include "../../Marlin.h"
|
||||
|
||||
// Based on selected port, use the proper configuration
|
||||
#if SERIAL_PORT == -1
|
||||
// If not using the USB port as serial port
|
||||
#if SERIAL_PORT >= 0
|
||||
|
||||
// Based on selected port, use the proper configuration
|
||||
#if SERIAL_PORT == 0
|
||||
#define HWUART UART
|
||||
#define HWUART_IRQ UART_IRQn
|
||||
#define HWUART_IRQ_ID ID_UART
|
||||
#elif SERIAL_PORT == 0
|
||||
#define HWUART USART0
|
||||
#elif SERIAL_PORT == 1
|
||||
#define HWUART ((Uart*)USART0)
|
||||
#define HWUART_IRQ USART0_IRQn
|
||||
#define HWUART_IRQ_ID ID_USART0
|
||||
#elif SERIAL_PORT == 1
|
||||
#define HWUART USART1
|
||||
#elif SERIAL_PORT == 2
|
||||
#define HWUART ((Uart*)USART1)
|
||||
#define HWUART_IRQ USART1_IRQn
|
||||
#define HWUART_IRQ_ID ID_USART1
|
||||
#elif SERIAL_PORT == 2
|
||||
#define HWUART USART2
|
||||
#elif SERIAL_PORT == 3
|
||||
#define HWUART ((Uart*)USART2)
|
||||
#define HWUART_IRQ USART2_IRQn
|
||||
#define HWUART_IRQ_ID ID_USART2
|
||||
#elif SERIAL_PORT == 3
|
||||
#define HWUART USART3
|
||||
#elif SERIAL_PORT == 4
|
||||
#define HWUART ((Uart*)USART3)
|
||||
#define HWUART_IRQ USART3_IRQn
|
||||
#define HWUART_IRQ_ID ID_USART3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct ring_buffer_r {
|
||||
struct ring_buffer_r {
|
||||
unsigned char buffer[RX_BUFFER_SIZE];
|
||||
volatile ring_buffer_pos_t head, tail;
|
||||
};
|
||||
};
|
||||
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
struct ring_buffer_t {
|
||||
unsigned char buffer[TX_BUFFER_SIZE];
|
||||
volatile uint8_t head, tail;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
|
||||
static bool _written;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80; // XON / XOFF Character was sent
|
||||
constexpr uint8_t XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
|
||||
// XON / XOFF character definitions
|
||||
|
@ -90,20 +93,20 @@ ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
|
|||
#if RX_BUFFER_SIZE < 4096
|
||||
#error Arduino DUE requires at least 4096 bytes of RX buffer to avoid buffer overflows when using XON/XOFF handshake
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
uint8_t rx_dropped_bytes = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
ring_buffer_pos_t rx_max_enqueued = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() asm volatile("": : :"memory");
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() asm volatile("": : :"memory");
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
|
||||
// Currently looking for: M108, M112, M410
|
||||
// If you alter the parser please don't forget to update the capabilities in Conditionals_post.h
|
||||
|
@ -190,9 +193,9 @@ ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
|
|||
}
|
||||
}
|
||||
|
||||
#endif // EMERGENCY_PARSER
|
||||
#endif // EMERGENCY_PARSER
|
||||
|
||||
FORCE_INLINE void store_rxd_char() {
|
||||
FORCE_INLINE void store_rxd_char() {
|
||||
|
||||
const ring_buffer_pos_t h = rx_buffer.head,
|
||||
i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1);
|
||||
|
@ -266,9 +269,9 @@ FORCE_INLINE void store_rxd_char() {
|
|||
#if ENABLED(EMERGENCY_PARSER)
|
||||
emergency_parser(c);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
|
||||
FORCE_INLINE void _tx_thr_empty_irq(void) {
|
||||
// If interrupts are enabled, there must be more data in the output
|
||||
|
@ -294,9 +297,9 @@ FORCE_INLINE void store_rxd_char() {
|
|||
HWUART->UART_IDR = UART_IDR_TXRDY;
|
||||
}
|
||||
|
||||
#endif // TX_BUFFER_SIZE > 0
|
||||
#endif // TX_BUFFER_SIZE > 0
|
||||
|
||||
static void UART_ISR(void) {
|
||||
static void UART_ISR(void) {
|
||||
uint32_t status = HWUART->UART_SR;
|
||||
|
||||
// Did we receive data?
|
||||
|
@ -314,11 +317,11 @@ static void UART_ISR(void) {
|
|||
// TODO: error reporting outside ISR
|
||||
HWUART->UART_CR = UART_CR_RSTSTA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Public Methods
|
||||
// Public Methods
|
||||
|
||||
void MarlinSerial::begin(const long baud_setting) {
|
||||
void MarlinSerial::begin(const long baud_setting) {
|
||||
|
||||
// Disable UART interrupt in NVIC
|
||||
NVIC_DisableIRQ( HWUART_IRQ );
|
||||
|
@ -357,31 +360,31 @@ void MarlinSerial::begin(const long baud_setting) {
|
|||
#if TX_BUFFER_SIZE > 0
|
||||
_written = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::end() {
|
||||
void MarlinSerial::end() {
|
||||
// Disable UART interrupt in NVIC
|
||||
NVIC_DisableIRQ( HWUART_IRQ );
|
||||
|
||||
pmc_disable_periph_clk( HWUART_IRQ_ID );
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::checkRx(void) {
|
||||
void MarlinSerial::checkRx(void) {
|
||||
if (HWUART->UART_SR & UART_SR_RXRDY) {
|
||||
CRITICAL_SECTION_START;
|
||||
store_rxd_char();
|
||||
CRITICAL_SECTION_END;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int MarlinSerial::peek(void) {
|
||||
int MarlinSerial::peek(void) {
|
||||
CRITICAL_SECTION_START;
|
||||
const int v = rx_buffer.head == rx_buffer.tail ? -1 : rx_buffer.buffer[rx_buffer.tail];
|
||||
CRITICAL_SECTION_END;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
int MarlinSerial::read(void) {
|
||||
int MarlinSerial::read(void) {
|
||||
int v;
|
||||
CRITICAL_SECTION_START;
|
||||
const ring_buffer_pos_t t = rx_buffer.tail;
|
||||
|
@ -408,16 +411,16 @@ int MarlinSerial::read(void) {
|
|||
}
|
||||
CRITICAL_SECTION_END;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
ring_buffer_pos_t MarlinSerial::available(void) {
|
||||
ring_buffer_pos_t MarlinSerial::available(void) {
|
||||
CRITICAL_SECTION_START;
|
||||
const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
|
||||
CRITICAL_SECTION_END;
|
||||
return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::flush(void) {
|
||||
void MarlinSerial::flush(void) {
|
||||
// Don't change this order of operations. If the RX interrupt occurs between
|
||||
// reading rx_buffer_head and updating rx_buffer_tail, the previous rx_buffer_head
|
||||
// may be written to rx_buffer_tail, making the buffer appear full rather than empty.
|
||||
|
@ -431,9 +434,9 @@ void MarlinSerial::flush(void) {
|
|||
writeNoHandshake(XON_CHAR);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
#if TX_BUFFER_SIZE > 0
|
||||
|
||||
uint8_t MarlinSerial::availableForWrite(void) {
|
||||
CRITICAL_SECTION_START;
|
||||
|
@ -514,7 +517,7 @@ void MarlinSerial::flush(void) {
|
|||
// the hardware finished tranmission (TXEMPTY is set).
|
||||
}
|
||||
|
||||
#else // TX_BUFFER_SIZE == 0
|
||||
#else // TX_BUFFER_SIZE == 0
|
||||
|
||||
void MarlinSerial::write(const uint8_t c) {
|
||||
#if ENABLED(SERIAL_XON_XOFF)
|
||||
|
@ -533,29 +536,29 @@ void MarlinSerial::flush(void) {
|
|||
HWUART->UART_THR = c;
|
||||
}
|
||||
|
||||
#endif // TX_BUFFER_SIZE == 0
|
||||
#endif // TX_BUFFER_SIZE == 0
|
||||
|
||||
/**
|
||||
* Imports from print.h
|
||||
*/
|
||||
/**
|
||||
* Imports from print.h
|
||||
*/
|
||||
|
||||
void MarlinSerial::print(char c, int base) {
|
||||
void MarlinSerial::print(char c, int base) {
|
||||
print((long)c, base);
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::print(unsigned char b, int base) {
|
||||
void MarlinSerial::print(unsigned char b, int base) {
|
||||
print((unsigned long)b, base);
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::print(int n, int base) {
|
||||
void MarlinSerial::print(int n, int base) {
|
||||
print((long)n, base);
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::print(unsigned int n, int base) {
|
||||
void MarlinSerial::print(unsigned int n, int base) {
|
||||
print((unsigned long)n, base);
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::print(long n, int base) {
|
||||
void MarlinSerial::print(long n, int base) {
|
||||
if (base == 0)
|
||||
write(n);
|
||||
else if (base == 10) {
|
||||
|
@ -567,70 +570,70 @@ void MarlinSerial::print(long n, int base) {
|
|||
}
|
||||
else
|
||||
printNumber(n, base);
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::print(unsigned long n, int base) {
|
||||
void MarlinSerial::print(unsigned long n, int base) {
|
||||
if (base == 0) write(n);
|
||||
else printNumber(n, base);
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::print(double n, int digits) {
|
||||
void MarlinSerial::print(double n, int digits) {
|
||||
printFloat(n, digits);
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::println(void) {
|
||||
void MarlinSerial::println(void) {
|
||||
print('\r');
|
||||
print('\n');
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::println(const String& s) {
|
||||
void MarlinSerial::println(const String& s) {
|
||||
print(s);
|
||||
println();
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::println(const char c[]) {
|
||||
void MarlinSerial::println(const char c[]) {
|
||||
print(c);
|
||||
println();
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::println(char c, int base) {
|
||||
void MarlinSerial::println(char c, int base) {
|
||||
print(c, base);
|
||||
println();
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::println(unsigned char b, int base) {
|
||||
void MarlinSerial::println(unsigned char b, int base) {
|
||||
print(b, base);
|
||||
println();
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::println(int n, int base) {
|
||||
void MarlinSerial::println(int n, int base) {
|
||||
print(n, base);
|
||||
println();
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::println(unsigned int n, int base) {
|
||||
void MarlinSerial::println(unsigned int n, int base) {
|
||||
print(n, base);
|
||||
println();
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::println(long n, int base) {
|
||||
void MarlinSerial::println(long n, int base) {
|
||||
print(n, base);
|
||||
println();
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::println(unsigned long n, int base) {
|
||||
void MarlinSerial::println(unsigned long n, int base) {
|
||||
print(n, base);
|
||||
println();
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::println(double n, int digits) {
|
||||
void MarlinSerial::println(double n, int digits) {
|
||||
print(n, digits);
|
||||
println();
|
||||
}
|
||||
}
|
||||
|
||||
// Private Methods
|
||||
// Private Methods
|
||||
|
||||
void MarlinSerial::printNumber(unsigned long n, uint8_t base) {
|
||||
void MarlinSerial::printNumber(unsigned long n, uint8_t base) {
|
||||
if (n) {
|
||||
unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
|
||||
int8_t i = 0;
|
||||
|
@ -643,9 +646,9 @@ void MarlinSerial::printNumber(unsigned long n, uint8_t base) {
|
|||
}
|
||||
else
|
||||
print('0');
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinSerial::printFloat(double number, uint8_t digits) {
|
||||
void MarlinSerial::printFloat(double number, uint8_t digits) {
|
||||
// Handle negative numbers
|
||||
if (number < 0.0) {
|
||||
print('-');
|
||||
|
@ -675,9 +678,10 @@ void MarlinSerial::printFloat(double number, uint8_t digits) {
|
|||
remainder -= toPrint;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Preinstantiate
|
||||
MarlinSerial customizedSerial;
|
||||
// Preinstantiate
|
||||
MarlinSerial customizedSerial;
|
||||
#endif
|
||||
|
||||
#endif // ARDUINO_ARCH_SAM
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
* Description: Fast IO functions for Arduino Due and compatible (SAM3X8E)
|
||||
*
|
||||
* For ARDUINO_ARCH_SAM
|
||||
* Note the code here was specifically crafted by disassembling what GCC produces
|
||||
* out of it, so GCC is able to optimize it out as much as possible to the least
|
||||
* amount of instructions. Be very carefull if you modify them, as "clean code"
|
||||
* leads to less efficient compiled code!!
|
||||
*/
|
||||
|
||||
#ifndef _FASTIO_DUE_H
|
||||
|
@ -55,13 +59,20 @@
|
|||
#define _READ(IO) ((bool)(DIO ## IO ## _WPORT -> PIO_PDSR & (MASK(DIO ## IO ## _PIN))))
|
||||
|
||||
/// Write to a pin
|
||||
#define _WRITE_VAR(IO, v) do { if (v) {g_APinDescription[IO].pPort->PIO_SODR = g_APinDescription[IO].ulPin; } \
|
||||
else {g_APinDescription[IO].pPort->PIO_CODR = g_APinDescription[IO].ulPin; } \
|
||||
} while (0)
|
||||
#define _WRITE_VAR(IO, v) do { \
|
||||
volatile Pio* port = g_APinDescription[IO].pPort; \
|
||||
uint32_t mask = g_APinDescription[IO].ulPin; \
|
||||
if (v) port->PIO_SODR = mask; \
|
||||
else port->PIO_CODR = mask; \
|
||||
} while(0)
|
||||
|
||||
#define _WRITE(IO, v) do { if (v) {DIO ## IO ## _WPORT -> PIO_SODR = MASK(DIO ## IO ##_PIN); } \
|
||||
else {DIO ## IO ## _WPORT -> PIO_CODR = MASK(DIO ## IO ## _PIN); }; \
|
||||
} while (0)
|
||||
/// Write to a pin
|
||||
#define _WRITE(IO, v) do { \
|
||||
volatile Pio* port = (DIO ## IO ## _WPORT); \
|
||||
uint32_t mask = MASK(DIO ## IO ## _PIN); \
|
||||
if (v) port->PIO_SODR = mask; \
|
||||
else port->PIO_CODR = mask; \
|
||||
} while(0)
|
||||
|
||||
/// toggle a pin
|
||||
#define _TOGGLE(IO) _WRITE(IO, !READ(IO))
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#if ENABLED(EEPROM_SETTINGS)
|
||||
|
||||
extern void eeprom_flush(void);
|
||||
|
||||
namespace HAL {
|
||||
namespace PersistentStore {
|
||||
|
||||
|
@ -14,6 +16,9 @@ bool access_start() {
|
|||
}
|
||||
|
||||
bool access_finish(){
|
||||
#if DISABLED(I2C_EEPROM) && DISABLED(SPI_EEPROM)
|
||||
eeprom_flush();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#define MOSI_PIN 51
|
||||
#endif
|
||||
|
||||
#define SS_PIN SDSS // A.28, A.29, B.21, C.26, C.29
|
||||
/* A.28, A.29, B.21, C.26, C.29 */
|
||||
#define SS_PIN SDSS
|
||||
|
||||
#endif /* SPI_PINS_H_ */
|
||||
|
|
1789
Marlin/src/config/examples/MakerParts/Configuration.h
Normal file
1789
Marlin/src/config/examples/MakerParts/Configuration.h
Normal file
File diff suppressed because it is too large
Load diff
1525
Marlin/src/config/examples/MakerParts/Configuration_adv.h
Normal file
1525
Marlin/src/config/examples/MakerParts/Configuration_adv.h
Normal file
File diff suppressed because it is too large
Load diff
83
Marlin/src/config/examples/MakerParts/_Bootscreen.h
Normal file
83
Marlin/src/config/examples/MakerParts/_Bootscreen.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Custom Bitmap for splashscreen
|
||||
*
|
||||
* You may use one of the following tools to generate the C++ bitmap array from
|
||||
* a black and white image:
|
||||
*
|
||||
* - http://www.marlinfw.org/tools/u8glib/converter.html
|
||||
* - http://www.digole.com/tools/PicturetoC_Hex_converter.php
|
||||
*/
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#define CUSTOM_BOOTSCREEN_TIMEOUT 2500
|
||||
#define CUSTOM_BOOTSCREEN_BMPWIDTH 128
|
||||
#define CUSTOM_BOOTSCREEN_BMPHEIGHT 44
|
||||
|
||||
const unsigned char custom_start_bmp[] PROGMEM = {
|
||||
0x00,0x1f,0xff,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
,0x00,0xff,0xff,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
,0x07,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
,0x1f,0xff,0xff,0xff,0xc0,0x0f,0x80,0x7c,0x07,0xe0,0x3f,0x0f,0xdf,0xff,0x7f,0xf0
|
||||
,0x3f,0xff,0xff,0xff,0xe0,0x0f,0xc0,0xfc,0x07,0xe0,0x3f,0x1f,0x9f,0xff,0x7f,0xfc
|
||||
,0x7f,0xbf,0xff,0xef,0xf0,0x0f,0xc0,0xfc,0x0f,0xf0,0x3f,0x1f,0x1f,0xff,0x7f,0xfe
|
||||
,0x7e,0x0f,0xff,0x83,0xf0,0x0f,0xe1,0xfc,0x0f,0xf0,0x3f,0x3e,0x1f,0xff,0x7f,0xfe
|
||||
,0x7c,0x07,0xff,0x01,0xf0,0x0f,0xe1,0xfc,0x1f,0xf8,0x3f,0x7e,0x1f,0x80,0x7c,0x3e
|
||||
,0x7c,0x03,0xfe,0x01,0xf0,0x0f,0xf3,0xfc,0x1f,0xf8,0x3f,0xfc,0x1f,0x80,0x7c,0x1e
|
||||
,0x7c,0x01,0xfc,0x01,0xf0,0x0f,0xf3,0xfc,0x1f,0xf8,0x3f,0xf8,0x1f,0xfc,0x7c,0x3e
|
||||
,0x7c,0x00,0xf8,0x01,0xf0,0x0f,0xff,0xfc,0x3e,0x7c,0x3f,0xf8,0x1f,0xfc,0x7f,0xfe
|
||||
,0x7c,0x00,0x70,0x01,0xf0,0x0f,0xff,0xfc,0x3e,0x7c,0x3f,0xfc,0x1f,0xfc,0x7f,0xfe
|
||||
,0x7c,0x00,0x20,0x01,0xf0,0x0f,0xff,0xfc,0x3e,0x7c,0x3f,0xfc,0x1f,0xfc,0x7f,0xfc
|
||||
,0x7c,0x00,0x00,0x01,0xf0,0x0f,0xbf,0x7c,0x7f,0xfe,0x3f,0xfe,0x1f,0xfc,0x7f,0xf8
|
||||
,0x7c,0x00,0x00,0x01,0xf0,0x0f,0xbf,0x7c,0x7f,0xfe,0x3f,0xfe,0x1f,0x80,0x7f,0xf8
|
||||
,0x7c,0x00,0x00,0x01,0xf0,0x0f,0x9e,0x7c,0x7f,0xfe,0x3f,0x3f,0x1f,0x80,0x7c,0xf8
|
||||
,0x7c,0x06,0x03,0x01,0xf0,0x0f,0x9e,0x7c,0xff,0xff,0x3f,0x3f,0x1f,0xff,0x7c,0xfc
|
||||
,0x7c,0x07,0x07,0x01,0xf0,0x0f,0x8c,0x7c,0xff,0xff,0x3f,0x1f,0x9f,0xff,0x7c,0xfc
|
||||
,0x7c,0x07,0x8f,0x01,0xf0,0x0f,0x80,0x7c,0xf8,0x1f,0x3f,0x1f,0x9f,0xff,0x7c,0x7e
|
||||
,0x7c,0x07,0xdf,0x01,0xf0,0x0f,0x80,0x7d,0xf8,0x1f,0xbf,0x0f,0xdf,0xff,0x7c,0x3f
|
||||
,0x7c,0x07,0xff,0x01,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
,0x7c,0x07,0xff,0x01,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
,0x7c,0x07,0xff,0x01,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
,0x7c,0x07,0xff,0x01,0xf0,0x0f,0xfe,0x03,0xf0,0x1f,0xf8,0x3f,0xff,0x87,0xf8,0x00
|
||||
,0x7c,0x07,0xff,0x01,0xf0,0x0f,0xff,0x03,0xf0,0x1f,0xfe,0x3f,0xff,0x9f,0xfe,0x00
|
||||
,0x7c,0x07,0xff,0x01,0xe0,0x0f,0xff,0x87,0xf8,0x1f,0xff,0x3f,0xff,0x9f,0xfe,0x00
|
||||
,0x3c,0x0f,0xff,0x81,0xe0,0x0f,0xff,0xc7,0xf8,0x1f,0xff,0xbf,0xff,0xbf,0xfe,0x00
|
||||
,0x3c,0x0f,0xff,0x81,0xe0,0x0f,0xff,0xc7,0xf8,0x1f,0xff,0xbf,0xff,0xbf,0x3c,0x00
|
||||
,0x1e,0x0f,0xff,0x83,0xc0,0x0f,0x87,0xcf,0xfc,0x1f,0x0f,0xc1,0xf0,0x3e,0x00,0x00
|
||||
,0x1e,0x0f,0xff,0x83,0xc0,0x0f,0x83,0xcf,0xfc,0x1f,0x07,0xc1,0xf0,0x3f,0xc0,0x00
|
||||
,0x0f,0x0f,0xff,0x87,0x80,0x0f,0x87,0xcf,0x3c,0x1f,0x0f,0x81,0xf0,0x3f,0xf8,0x00
|
||||
,0x0f,0x0f,0xff,0x87,0x80,0x0f,0xff,0xdf,0x3e,0x1f,0xff,0x81,0xf0,0x1f,0xfe,0x00
|
||||
,0x07,0x8f,0xff,0x8f,0x00,0x0f,0xff,0x9f,0x3e,0x1f,0xff,0x81,0xf0,0x1f,0xfe,0x00
|
||||
,0x07,0xcf,0xff,0x9f,0x00,0x0f,0xff,0x1f,0x3e,0x1f,0xff,0x01,0xf0,0x07,0xff,0x00
|
||||
,0x03,0xef,0xff,0xbe,0x00,0x0f,0xfc,0x3f,0xff,0x1f,0xfe,0x01,0xf0,0x00,0x7f,0x00
|
||||
,0x01,0xef,0xff,0xbc,0x00,0x0f,0x80,0x3f,0xff,0x1f,0x3e,0x01,0xf0,0x18,0x1f,0x00
|
||||
,0x00,0xef,0xff,0xb8,0x00,0x0f,0x80,0x3f,0xff,0x1f,0x3f,0x01,0xf0,0x1e,0x3f,0x7c
|
||||
,0x00,0x6f,0xff,0xb0,0x00,0x0f,0x80,0x7f,0xff,0x9f,0x3f,0x01,0xf0,0x3f,0xff,0x7c
|
||||
,0x00,0x2f,0xff,0xa0,0x00,0x0f,0x80,0x7f,0xff,0x9f,0x1f,0x81,0xf0,0x7f,0xfe,0x7c
|
||||
,0x00,0x0f,0xff,0x80,0x00,0x0f,0x80,0x7c,0x0f,0x9f,0x1f,0x81,0xf0,0x3f,0xfe,0x7c
|
||||
,0x00,0x0f,0xff,0x80,0x00,0x0f,0x80,0xfc,0x0f,0xdf,0x0f,0xc1,0xf0,0x0f,0xf8,0x7c
|
||||
,0x00,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
,0x00,0x03,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
};
|
|
@ -35,6 +35,7 @@
|
|||
#define _YMAX_ 201
|
||||
#define _ZMAX_ 301
|
||||
|
||||
#define _FORCE_INLINE_ __attribute__((__always_inline__)) __inline__
|
||||
#define FORCE_INLINE __attribute__((always_inline)) inline
|
||||
#define _UNUSED __attribute__((unused))
|
||||
#define _O0 __attribute__((optimize("O0")))
|
||||
|
|
|
@ -62,6 +62,13 @@ class U8GLIB_ST7920_128X64_RRD : public U8GLIB
|
|||
};
|
||||
|
||||
|
||||
extern u8g_dev_t u8g_dev_st7920_128x64_custom_sw_spi;
|
||||
class U8GLIB_ST7920_128X64_CUSTOM_SW_SPI : public U8GLIB {
|
||||
public:
|
||||
U8GLIB_ST7920_128X64_CUSTOM_SW_SPI()
|
||||
: U8GLIB(&u8g_dev_st7920_128x64_custom_sw_spi)
|
||||
{ }
|
||||
};
|
||||
|
||||
extern u8g_dev_t u8g_dev_sh1106_128x64_2x_i2c_2_wire;
|
||||
class U8GLIB_SH1106_128X64_2X_I2C_2_WIRE : public U8GLIB {
|
||||
|
|
276
Marlin/src/lcd/dogm/u8g_dev_st7920_128_64_sw_spi.cpp
Normal file
276
Marlin/src/lcd/dogm/u8g_dev_st7920_128_64_sw_spi.cpp
Normal file
|
@ -0,0 +1,276 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* PLEASE NOTE >>>
|
||||
* We need our custom implementation for Software SPI, as the default implementation
|
||||
* of U8GLIB, when running in an ARM based board, is too fast and the display will not
|
||||
* recognize commands and/or data at such speeds. This implementation autoderives the
|
||||
* required delays to get the maximum possible performance by using the F_CPU macro that
|
||||
* specifies the CPU speed. According to the ST7920 datasheet, the maximum SCLK is 1MHz.
|
||||
*/
|
||||
|
||||
#ifndef ULCDST7920_SWSPI_H
|
||||
#define ULCDST7920_SWSPI_H
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(U8GLIB_ST7920)
|
||||
|
||||
#include <U8glib.h>
|
||||
#include "HAL_LCD_com_defines.h"
|
||||
|
||||
#define ST7920_CLK_PIN LCD_PINS_D4
|
||||
#define ST7920_DAT_PIN LCD_PINS_ENABLE
|
||||
#define ST7920_CS_PIN LCD_PINS_RS
|
||||
|
||||
//#define PAGE_HEIGHT 8 //128 byte framebuffer
|
||||
#define PAGE_HEIGHT 16 //256 byte framebuffer
|
||||
//#define PAGE_HEIGHT 32 //512 byte framebuffer
|
||||
|
||||
#define LCD_PIXEL_WIDTH 128
|
||||
#define LCD_PIXEL_HEIGHT 64
|
||||
|
||||
//set optimization so ARDUINO optimizes this file
|
||||
#pragma GCC optimize (3)
|
||||
|
||||
/* ---------------- Delay Cycles routine -------------- */
|
||||
|
||||
#ifdef __arm__
|
||||
/* https://blueprints.launchpad.net/gcc-arm-embedded/+spec/delay-cycles */
|
||||
|
||||
#define nop() __asm__ __volatile__("nop;\n\t":::)
|
||||
|
||||
FORCE_INLINE static void __delay_4cycles(uint32_t cy) { // +1 cycle
|
||||
#if ARCH_PIPELINE_RELOAD_CYCLES<2
|
||||
#define EXTRA_NOP_CYCLES "nop"
|
||||
#else
|
||||
#define EXTRA_NOP_CYCLES ""
|
||||
#endif
|
||||
|
||||
__asm__ __volatile__(
|
||||
".syntax unified" "\n\t" // is to prevent CM0,CM1 non-unified syntax
|
||||
|
||||
"loop%=:" "\n\t"
|
||||
" subs %[cnt],#1" "\n\t"
|
||||
EXTRA_NOP_CYCLES "\n\t"
|
||||
" bne loop%=" "\n\t"
|
||||
: [cnt]"+r"(cy) // output: +r means input+output
|
||||
: // input:
|
||||
: "cc" // clobbers:
|
||||
);
|
||||
}
|
||||
|
||||
FORCE_INLINE static void DELAY_CYCLES(uint32_t x) {
|
||||
|
||||
if (__builtin_constant_p(x)) {
|
||||
|
||||
#define MAXNOPS 4
|
||||
|
||||
if (x <= (MAXNOPS)) {
|
||||
switch(x) { case 4: nop(); case 3: nop(); case 2: nop(); case 1: nop(); }
|
||||
}
|
||||
else { // because of +1 cycle inside delay_4cycles
|
||||
const uint32_t rem = (x - 1) % (MAXNOPS);
|
||||
switch(rem) { case 3: nop(); case 2: nop(); case 1: nop(); }
|
||||
if ((x = (x - 1) / (MAXNOPS)))
|
||||
__delay_4cycles(x); // if need more then 4 nop loop is more optimal
|
||||
}
|
||||
}
|
||||
else
|
||||
__delay_4cycles(x / 4);
|
||||
}
|
||||
|
||||
#ifdef __TEST_DELAY
|
||||
|
||||
void calibrateTimer() {
|
||||
|
||||
// Use DWT to calibrate cycles
|
||||
uint32_t count = 0;
|
||||
|
||||
// addresses of registers
|
||||
volatile uint32_t *DWT_CONTROL = (uint32_t *)0xE0001000,
|
||||
*DWT_CYCCNT = (uint32_t *)0xE0001004,
|
||||
*DEMCR = (uint32_t *)0xE000EDFC;
|
||||
|
||||
cli();
|
||||
|
||||
// enable the use DWT
|
||||
*DEMCR = *DEMCR | 0x01000000;
|
||||
|
||||
// Reset cycle counter
|
||||
*DWT_CYCCNT = 0;
|
||||
|
||||
// enable cycle counter
|
||||
*DWT_CONTROL = *DWT_CONTROL | 1;
|
||||
|
||||
// Perform a delay of 10000 cycles
|
||||
DELAY_CYCLES(10000U);
|
||||
|
||||
// number of cycles stored in count variable
|
||||
count = *DWT_CYCCNT;
|
||||
|
||||
sei();
|
||||
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOLNPAIR("calibrated Cycles: ", (int)count);
|
||||
}
|
||||
|
||||
#endif // __TEST_DELAY
|
||||
|
||||
#elif defined(__AVR__)
|
||||
#define DELAY_CYCLES(cycles) __builtin_avr_delay_cycles(cycles)
|
||||
#else
|
||||
#error "DELAY_CYCLES not implemented for this architecture."
|
||||
#endif
|
||||
|
||||
/* ---------------- Delay in nanoseconds and in microseconds */
|
||||
|
||||
#define DELAY_NS(x) DELAY_CYCLES( (x) * (F_CPU/1000000) / 1000)
|
||||
#define DELAY_US(x) DELAY_CYCLES( (x) * (F_CPU/1000000))
|
||||
|
||||
/* ---------------- ST7920 commands ------------------------ */
|
||||
|
||||
#ifdef __arm__
|
||||
|
||||
/* ARM: Plain implementation is more than enough */
|
||||
static void ST7920_SWSPI_SND_8BIT(uint8_t val) {
|
||||
uint8_t n = 8;
|
||||
do {
|
||||
WRITE(ST7920_CLK_PIN, LOW);
|
||||
WRITE(ST7920_DAT_PIN, val & 0x80);
|
||||
DELAY_NS(500);
|
||||
WRITE(ST7920_CLK_PIN, HIGH);
|
||||
DELAY_NS(500);
|
||||
val <<= 1;
|
||||
} while (--n);
|
||||
}
|
||||
|
||||
#else // !ARM
|
||||
|
||||
/* AVR: Unrolling loop makes sense */
|
||||
#define ST7920_SND_BIT(nr) \
|
||||
WRITE(ST7920_CLK_PIN, LOW); \
|
||||
WRITE(ST7920_DAT_PIN, TEST(val, nr)); \
|
||||
DELAY_NS(500); \
|
||||
WRITE(ST7920_CLK_PIN, HIGH); \
|
||||
DELAY_NS(500);
|
||||
|
||||
static void ST7920_SWSPI_SND_8BIT(const uint8_t val) {
|
||||
ST7920_SND_BIT(7); // MSBit
|
||||
ST7920_SND_BIT(6); //
|
||||
ST7920_SND_BIT(5); //
|
||||
ST7920_SND_BIT(4); //
|
||||
ST7920_SND_BIT(3); //
|
||||
ST7920_SND_BIT(2); //
|
||||
ST7920_SND_BIT(1); //
|
||||
ST7920_SND_BIT(0); // LSBit
|
||||
}
|
||||
|
||||
#endif // !ARM
|
||||
|
||||
#define ST7920_CS() { WRITE(ST7920_CS_PIN,1); DELAY_NS(200); }
|
||||
#define ST7920_NCS() { WRITE(ST7920_CS_PIN,0); }
|
||||
#define ST7920_SET_CMD() { ST7920_SWSPI_SND_8BIT(0xF8); DELAY_US(3); }
|
||||
#define ST7920_SET_DAT() { ST7920_SWSPI_SND_8BIT(0xFA); DELAY_US(3); }
|
||||
#define ST7920_WRITE_BYTE(a) { ST7920_SWSPI_SND_8BIT((uint8_t)((a)&0xF0u)); ST7920_SWSPI_SND_8BIT((uint8_t)((a)<<4u)); DELAY_US(3); }
|
||||
#define ST7920_WRITE_BYTES(p,l) { for (uint8_t i = l + 1; --i;) { ST7920_SWSPI_SND_8BIT(*p&0xF0); ST7920_SWSPI_SND_8BIT(*p<<4); p++; } DELAY_US(3); }
|
||||
|
||||
|
||||
uint8_t u8g_dev_st7920_custom_sw_spi_128x64_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) {
|
||||
|
||||
uint8_t i, y;
|
||||
switch (msg) {
|
||||
case U8G_DEV_MSG_INIT: {
|
||||
|
||||
/* Set to output and write */
|
||||
OUT_WRITE(ST7920_CS_PIN, LOW);
|
||||
OUT_WRITE(ST7920_DAT_PIN, LOW);
|
||||
OUT_WRITE(ST7920_CLK_PIN, HIGH);
|
||||
|
||||
ST7920_CS();
|
||||
u8g_Delay(120); //initial delay for boot up
|
||||
|
||||
ST7920_SET_CMD();
|
||||
ST7920_WRITE_BYTE(0x08); //display off, cursor+blink off
|
||||
ST7920_WRITE_BYTE(0x01); //clear CGRAM ram
|
||||
u8g_Delay(15); //delay for CGRAM clear
|
||||
ST7920_WRITE_BYTE(0x3E); //extended mode + GDRAM active
|
||||
for (y = 0; y < (LCD_PIXEL_HEIGHT) / 2; y++) { //clear GDRAM
|
||||
ST7920_WRITE_BYTE(0x80 | y); //set y
|
||||
ST7920_WRITE_BYTE(0x80); //set x = 0
|
||||
ST7920_SET_DAT();
|
||||
for (i = 0; i < 2 * (LCD_PIXEL_WIDTH) / 8; i++) //2x width clears both segments
|
||||
ST7920_WRITE_BYTE(0);
|
||||
ST7920_SET_CMD();
|
||||
}
|
||||
|
||||
ST7920_WRITE_BYTE(0x0C); //display on, cursor+blink off
|
||||
ST7920_NCS();
|
||||
}
|
||||
break;
|
||||
|
||||
case U8G_DEV_MSG_STOP:
|
||||
break;
|
||||
|
||||
case U8G_DEV_MSG_PAGE_NEXT: {
|
||||
u8g_pb_t* pb = (u8g_pb_t*)(dev->dev_mem);
|
||||
y = pb->p.page_y0;
|
||||
uint8_t* ptr = (uint8_t*)pb->buf;
|
||||
|
||||
ST7920_CS();
|
||||
for (i = 0; i < PAGE_HEIGHT; i ++) {
|
||||
ST7920_SET_CMD();
|
||||
if (y < 32) {
|
||||
ST7920_WRITE_BYTE(0x80 | y); //y
|
||||
ST7920_WRITE_BYTE(0x80); //x=0
|
||||
}
|
||||
else {
|
||||
ST7920_WRITE_BYTE(0x80 | (y - 32)); //y
|
||||
ST7920_WRITE_BYTE(0x80 | 8); //x=64
|
||||
}
|
||||
ST7920_SET_DAT();
|
||||
ST7920_WRITE_BYTES(ptr, (LCD_PIXEL_WIDTH) / 8); //ptr is incremented inside of macro
|
||||
y++;
|
||||
}
|
||||
|
||||
ST7920_NCS();
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if PAGE_HEIGHT == 8
|
||||
return u8g_dev_pb8h1_base_fn(u8g, dev, msg, arg);
|
||||
#elif PAGE_HEIGHT == 16
|
||||
return u8g_dev_pb16h1_base_fn(u8g, dev, msg, arg);
|
||||
#else
|
||||
return u8g_dev_pb32h1_base_fn(u8g, dev, msg, arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint8_t u8g_dev_st7920_128x64_custom_sw_spi_buf[(LCD_PIXEL_WIDTH) * (PAGE_HEIGHT) / 8] U8G_NOCOMMON;
|
||||
static u8g_pb_t u8g_dev_st7920_128x64_custom_sw_spi_pb = {{PAGE_HEIGHT, LCD_PIXEL_HEIGHT, 0, 0, 0}, LCD_PIXEL_WIDTH, u8g_dev_st7920_128x64_custom_sw_spi_buf};
|
||||
u8g_dev_t u8g_dev_st7920_128x64_custom_sw_spi = {u8g_dev_st7920_custom_sw_spi_128x64_fn, &u8g_dev_st7920_128x64_custom_sw_spi_pb, &u8g_com_null_fn};
|
||||
|
||||
#pragma GCC reset_options
|
||||
|
||||
#endif // U8GLIB_ST7920
|
||||
#endif // ULCDST7920_SWSPI_H
|
|
@ -169,6 +169,10 @@
|
|||
#else
|
||||
U8GLIB_ST7920_128X64_4X u8g(LCD_PINS_RS); // 2 stripes, HW SPI (shared with SD card)
|
||||
#endif
|
||||
#elif ENABLED(U8GLIB_ST7920) && defined(__arm__)
|
||||
// RepRap Discount Full Graphics Smart Controller on an ARM target
|
||||
U8GLIB_ST7920_128X64_CUSTOM_SW_SPI u8g;
|
||||
|
||||
#elif ENABLED(U8GLIB_ST7920)
|
||||
// RepRap Discount Full Graphics Smart Controller
|
||||
//U8GLIB_ST7920_128X64_4X u8g(LCD_PINS_RS); // 2 stripes, HW SPI (shared with SD card, on AVR does not use standard LCD adapter)
|
||||
|
@ -176,6 +180,7 @@
|
|||
U8GLIB_ST7920_128X64_RRD u8g(LCD_PINS_D4, LCD_PINS_ENABLE, LCD_PINS_RS); // Number of stripes can be adjusted in ultralcd_st7920_u8glib_rrd.h with PAGE_HEIGHT
|
||||
// AVR version ignores these pin settings
|
||||
// HAL version uses these pin settings
|
||||
|
||||
#elif ENABLED(CARTESIO_UI)
|
||||
// The CartesioUI display
|
||||
//U8GLIB_DOGM128_2X u8g(DOGLCD_SCK, DOGLCD_MOSI, DOGLCD_CS, DOGLCD_A0); // 4 stripes
|
||||
|
|
Loading…
Reference in a new issue