MKS-Sean
4 years ago
committed by
Scott Lahteine
51 changed files with 1270 additions and 649 deletions
@ -0,0 +1,352 @@ |
|||
/**
|
|||
* Marlin 3D Printer Firmware |
|||
* Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
|
|||
* |
|||
*/ |
|||
#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC) && !defined(MAPLE_STM32F1) |
|||
|
|||
#include "../../../inc/MarlinConfigPre.h" |
|||
|
|||
#if BOTH(HAS_TFT_LVGL_UI, MKS_WIFI_MODULE) |
|||
|
|||
#include "tft_lvgl_configuration.h" |
|||
|
|||
#include "draw_ui.h" |
|||
#include "wifiSerial.h" |
|||
|
|||
WifiSerial WifiSerial1(USART1); |
|||
|
|||
void WifiSerial::setRx(uint32_t _rx) { _serial.pin_rx = digitalPinToPinName(_rx); } |
|||
void WifiSerial::setTx(uint32_t _tx) { _serial.pin_tx = digitalPinToPinName(_tx); } |
|||
void WifiSerial::setRx(PinName _rx) { _serial.pin_rx = _rx; } |
|||
void WifiSerial::setTx(PinName _tx) { _serial.pin_tx = _tx; } |
|||
|
|||
void WifiSerial::init(PinName _rx, PinName _tx) { |
|||
_serial.pin_rx = (_rx == _tx) ? NC : _rx; |
|||
_serial.pin_tx = _tx; |
|||
_serial.rx_buff = wifiRxBuf; |
|||
_serial.rx_head = 0; |
|||
_serial.rx_tail = 0; |
|||
_serial.tx_buff = wifiTxBuf; |
|||
_serial.tx_head = 0; |
|||
_serial.tx_tail = 0; |
|||
} |
|||
|
|||
WifiSerial::WifiSerial(void *peripheral) { |
|||
// If PIN_SERIALy_RX is not defined assume half-duplex
|
|||
_serial.pin_rx = NC; |
|||
// If Serial is defined in variant set
|
|||
// the Rx/Tx pins for com port if defined
|
|||
#if defined(Serial) && defined(PIN_SERIAL_TX) |
|||
if ((void *)this == (void *)&Serial) { |
|||
#ifdef PIN_SERIAL_RX |
|||
setRx(PIN_SERIAL_RX); |
|||
#endif |
|||
setTx(PIN_SERIAL_TX); |
|||
} else |
|||
#endif |
|||
#if defined(PIN_SERIAL1_TX) && defined(USART1_BASE) |
|||
if (peripheral == USART1) { |
|||
#ifdef PIN_SERIAL1_RX |
|||
setRx(PIN_SERIAL1_RX); |
|||
#endif |
|||
setTx(PIN_SERIAL1_TX); |
|||
} else |
|||
#endif |
|||
#if defined(PIN_SERIAL2_TX) && defined(USART2_BASE) |
|||
if (peripheral == USART2) { |
|||
#ifdef PIN_SERIAL2_RX |
|||
setRx(PIN_SERIAL2_RX); |
|||
#endif |
|||
setTx(PIN_SERIAL2_TX); |
|||
} else |
|||
#endif |
|||
#if defined(PIN_SERIAL3_TX) && defined(USART3_BASE) |
|||
if (peripheral == USART3) { |
|||
#ifdef PIN_SERIAL3_RX |
|||
setRx(PIN_SERIAL3_RX); |
|||
#endif |
|||
setTx(PIN_SERIAL3_TX); |
|||
} else |
|||
#endif |
|||
#ifdef PIN_SERIAL4_TX |
|||
if (false |
|||
#ifdef USART4_BASE |
|||
|| peripheral == USART4 |
|||
#elif defined(UART4_BASE) |
|||
|| peripheral == UART4 |
|||
#endif |
|||
) { |
|||
#ifdef PIN_SERIAL4_RX |
|||
setRx(PIN_SERIAL4_RX); |
|||
#endif |
|||
setTx(PIN_SERIAL4_TX); |
|||
} else |
|||
#endif |
|||
#ifdef PIN_SERIAL5_TX |
|||
if (false |
|||
#ifdef USART5_BASE |
|||
|| peripheral == USART5 |
|||
#elif defined(UART5_BASE) |
|||
|| peripheral == UART5 |
|||
#endif |
|||
) { |
|||
#ifdef PIN_SERIAL5_RX |
|||
setRx(PIN_SERIAL5_RX); |
|||
#endif |
|||
setTx(PIN_SERIAL5_TX); |
|||
} else |
|||
#endif |
|||
#if defined(PIN_SERIAL6_TX) && defined(USART6_BASE) |
|||
if (peripheral == USART6) { |
|||
#ifdef PIN_SERIAL6_RX |
|||
setRx(PIN_SERIAL6_RX); |
|||
#endif |
|||
setTx(PIN_SERIAL6_TX); |
|||
} else |
|||
#endif |
|||
#ifdef PIN_SERIAL7_TX |
|||
if (false |
|||
#ifdef USART7_BASE |
|||
|| peripheral == USART7 |
|||
#elif defined(UART7_BASE) |
|||
|| peripheral == UART7 |
|||
#endif |
|||
) { |
|||
#ifdef PIN_SERIAL7_RX |
|||
setRx(PIN_SERIAL7_RX); |
|||
#endif |
|||
setTx(PIN_SERIAL7_TX); |
|||
} else |
|||
#endif |
|||
#ifdef PIN_SERIAL8_TX |
|||
if (false |
|||
#ifdef USART8_BASE |
|||
|| peripheral == USART8 |
|||
#elif defined(UART8_BASE) |
|||
|| peripheral == UART8 |
|||
#endif |
|||
) { |
|||
#ifdef PIN_SERIAL8_RX |
|||
setRx(PIN_SERIAL8_RX); |
|||
#endif |
|||
setTx(PIN_SERIAL8_TX); |
|||
} else |
|||
#endif |
|||
#if defined(PIN_SERIAL9_TX) && defined(UART9_BASE) |
|||
if (peripheral == UART9) { |
|||
#ifdef PIN_SERIAL9_RX |
|||
setRx(PIN_SERIAL9_RX); |
|||
#endif |
|||
setTx(PIN_SERIAL9_TX); |
|||
} else |
|||
#endif |
|||
#ifdef PIN_SERIAL10_TX |
|||
if (false |
|||
#ifdef USART10_BASE |
|||
|| peripheral == USART10 |
|||
#elif defined(UART10_BASE) |
|||
|| peripheral == UART10 |
|||
#endif |
|||
) { |
|||
#ifdef PIN_SERIAL10_RX |
|||
setRx(PIN_SERIAL10_RX); |
|||
#endif |
|||
setTx(PIN_SERIAL10_TX); |
|||
} else |
|||
#endif |
|||
#if defined(PIN_SERIALLP1_TX) && defined(LPUART1_BASE) |
|||
if (peripheral == LPUART1) { |
|||
#ifdef PIN_SERIALLP1_RX |
|||
setRx(PIN_SERIALLP1_RX); |
|||
#endif |
|||
setTx(PIN_SERIALLP1_TX); |
|||
} else |
|||
#endif |
|||
// else get the pins of the first peripheral occurrence in PinMap
|
|||
{ |
|||
_serial.pin_rx = pinmap_pin(peripheral, PinMap_UART_RX); |
|||
_serial.pin_tx = pinmap_pin(peripheral, PinMap_UART_TX); |
|||
} |
|||
//if (halfDuplex == HALF_DUPLEX_ENABLED) _serial.pin_rx = NC;
|
|||
init(_serial.pin_rx, _serial.pin_tx); |
|||
} |
|||
|
|||
void WifiSerial::flush() { |
|||
// If we have never written a byte, no need to flush. This special
|
|||
// case is needed since there is no way to force the TXC (transmit
|
|||
// complete) bit to 1 during initialization
|
|||
if (!_written) return; |
|||
|
|||
while ((_serial.tx_head != _serial.tx_tail)) { |
|||
// nop, the interrupt handler will free up space for us
|
|||
} |
|||
// If we get here, nothing is queued anymore (DRIE is disabled) and
|
|||
// the hardware finished tranmission (TXC is set).
|
|||
} |
|||
|
|||
bool WifiSerial::isHalfDuplex() const { return _serial.pin_rx == NC; } |
|||
|
|||
void WifiSerial::enableHalfDuplexRx() { |
|||
if (isHalfDuplex()) { |
|||
// In half-duplex mode we have to wait for all TX characters to
|
|||
// be transmitted before we can receive data.
|
|||
flush(); |
|||
if (!_rx_enabled) { |
|||
_rx_enabled = true; |
|||
uart_enable_rx(&_serial); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Actual interrupt handlers //////////////////////////////////////////////////////////////
|
|||
|
|||
void WifiSerial::_rx_complete_irq(serial_t *obj) { |
|||
// No Parity error, read byte and store it in the buffer if there is room
|
|||
unsigned char c; |
|||
|
|||
if (uart_getc(obj, &c) == 0) { |
|||
|
|||
WRITE(WIFI_IO1_PIN, HIGH); |
|||
|
|||
rx_buffer_index_t i = (unsigned int)(obj->rx_head + 1) % WIFI_RX_BUF_SIZE; |
|||
|
|||
// if we should be storing the received character into the location
|
|||
// just before the tail (meaning that the head would advance to the
|
|||
// current location of the tail), we're about to overflow the buffer
|
|||
// and so we don't write the character or advance the head.
|
|||
if (i != obj->rx_tail) { |
|||
obj->rx_buff[obj->rx_head] = c; |
|||
obj->rx_head = i; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Actual interrupt handlers //////////////////////////////////////////////////////////////
|
|||
|
|||
int WifiSerial::_tx_complete_irq(serial_t *obj) { |
|||
// If interrupts are enabled, there must be more data in the output
|
|||
// buffer. Send the next byte
|
|||
obj->tx_tail = (obj->tx_tail + 1) % WIFI_TX_BUF_SIZE; |
|||
|
|||
return (obj->tx_head == obj->tx_tail) ? -1 : 0; |
|||
} |
|||
|
|||
void WifiSerial::begin(unsigned long baud) { begin(baud, SERIAL_8N1); } |
|||
|
|||
void WifiSerial::begin(unsigned long baud, byte config) { |
|||
uint32_t databits = 0, stopbits = 0, parity = 0; |
|||
|
|||
_baud = baud; |
|||
_config = config; |
|||
|
|||
// Manage databits
|
|||
switch (config & 0x07) { |
|||
case 0x02: databits = 6; break; |
|||
case 0x04: databits = 7; break; |
|||
case 0x06: databits = 8; break; |
|||
default: databits = 0; break; |
|||
} |
|||
|
|||
if ((config & 0x30) == 0x30) { |
|||
parity = UART_PARITY_ODD; |
|||
databits++; |
|||
} |
|||
else if ((config & 0x20) == 0x20) { |
|||
parity = UART_PARITY_EVEN; |
|||
databits++; |
|||
} |
|||
else |
|||
parity = UART_PARITY_NONE; |
|||
|
|||
stopbits = ((config & 0x08) == 0x08) ? UART_STOPBITS_2 : UART_STOPBITS_1; |
|||
|
|||
switch (databits) { |
|||
#ifdef UART_WORDLENGTH_7B |
|||
case 7: databits = UART_WORDLENGTH_7B; break; |
|||
#endif |
|||
case 8: databits = UART_WORDLENGTH_8B; break; |
|||
case 9: databits = UART_WORDLENGTH_9B; break; |
|||
default: |
|||
case 0: Error_Handler(); break; |
|||
} |
|||
|
|||
uart_init(&_serial, (uint32_t)baud, databits, parity, stopbits); |
|||
enableHalfDuplexRx(); |
|||
if (baud == WIFI_BAUDRATE) |
|||
uart_attach_rx_callback(&_serial, _rx_complete_irq); |
|||
else |
|||
USART1->CR1 |= USART_CR1_RE; // Preserve word length, etc. Use 'or' to preserve USART_CR1_M_8N1
|
|||
} |
|||
|
|||
void WifiSerial::end() { |
|||
// wait for transmission of outgoing data
|
|||
flush(); |
|||
|
|||
uart_deinit(&_serial); |
|||
|
|||
// clear any received data
|
|||
_serial.rx_head = _serial.rx_tail; |
|||
} |
|||
|
|||
int WifiSerial::available() { |
|||
return ((unsigned int)(WIFI_RX_BUF_SIZE + _serial.rx_head - _serial.rx_tail)) % WIFI_RX_BUF_SIZE; |
|||
} |
|||
|
|||
//
|
|||
// I/O
|
|||
//
|
|||
int WifiSerial::read() { |
|||
enableHalfDuplexRx(); |
|||
// if the head isn't ahead of the tail, we don't have any characters
|
|||
if (_serial.rx_head == _serial.rx_tail) return -1; |
|||
|
|||
unsigned char c = _serial.rx_buff[_serial.rx_tail]; |
|||
_serial.rx_tail = (rx_buffer_index_t)(_serial.rx_tail + 1) % WIFI_RX_BUF_SIZE; |
|||
return c; |
|||
} |
|||
|
|||
int WifiSerial::write(uint8_t c) { |
|||
_written = true; |
|||
if (isHalfDuplex()) { |
|||
if (_rx_enabled) { |
|||
_rx_enabled = false; |
|||
uart_enable_tx(&_serial); |
|||
} |
|||
} |
|||
|
|||
tx_buffer_index_t i = (_serial.tx_head + 1) % WIFI_TX_BUF_SIZE; |
|||
|
|||
// If the output buffer is full, there's nothing for it other than to
|
|||
// wait for the interrupt handler to empty it a bit
|
|||
while (i == _serial.tx_tail) { |
|||
// nop, the interrupt handler will free up space for us
|
|||
} |
|||
|
|||
_serial.tx_buff[_serial.tx_head] = c; |
|||
_serial.tx_head = i; |
|||
|
|||
if (!serial_tx_active(&_serial)) |
|||
uart_attach_tx_callback(&_serial, _tx_complete_irq); |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
#endif // HAS_TFT_LVGL_UI && MKS_WIFI_MODULE
|
|||
#endif // !__STM32F1__
|
@ -0,0 +1,63 @@ |
|||
/**
|
|||
* Marlin 3D Printer Firmware |
|||
* Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
|
|||
* |
|||
*/ |
|||
#pragma once |
|||
|
|||
#include <inttypes.h> |
|||
#include "Stream.h" |
|||
#include "uart.h" |
|||
|
|||
class WifiSerial { |
|||
protected: |
|||
// Has any byte been written to the UART since begin()
|
|||
bool _written; |
|||
serial_t _serial; |
|||
public: |
|||
uint8_t wifiRxBuf[WIFI_RX_BUF_SIZE]; |
|||
uint8_t wifiTxBuf[WIFI_TX_BUF_SIZE]; |
|||
WifiSerial(void *peripheral); |
|||
|
|||
// Set up / tear down
|
|||
void begin(uint32_t baud); |
|||
void begin(uint32_t baud,uint8_t config); |
|||
void end(); |
|||
int available(void); |
|||
int read(void); |
|||
int write(uint8_t); |
|||
|
|||
// Interrupt handlers
|
|||
static int _tx_complete_irq(serial_t *obj); |
|||
static void _rx_complete_irq(serial_t *obj); |
|||
|
|||
void flush(void); |
|||
bool isHalfDuplex(void) const; |
|||
void enableHalfDuplexRx(void); |
|||
|
|||
private: |
|||
void setRx(uint32_t _rx); |
|||
void setTx(uint32_t _tx); |
|||
void setRx(PinName _rx); |
|||
void setTx(PinName _tx); |
|||
void init(PinName _rx, PinName _tx); |
|||
bool _rx_enabled; |
|||
uint8_t _config; |
|||
unsigned long _baud; |
|||
}; |
@ -0,0 +1,77 @@ |
|||
/**
|
|||
* Marlin 3D Printer Firmware |
|||
* Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
|
|||
* |
|||
*/ |
|||
#pragma once |
|||
|
|||
#include <libmaple/libmaple_types.h> |
|||
#include <libmaple/usart.h> |
|||
#include <libmaple/libmaple.h> |
|||
#include <libmaple/gpio.h> |
|||
#include <libmaple/timer.h> |
|||
#include <libmaple/ring_buffer.h> |
|||
|
|||
#define DEFINE_WFSERIAL(name, n) WifiSerial name(USART##n, BOARD_USART##n##_TX_PIN, BOARD_USART##n##_RX_PIN) |
|||
|
|||
class WifiSerial { |
|||
public: |
|||
uint8 wifiRxBuf[WIFI_RX_BUF_SIZE]; |
|||
|
|||
public: |
|||
WifiSerial(struct usart_dev *usart_device, uint8 tx_pin, uint8 rx_pin); |
|||
|
|||
/* Set up/tear down */ |
|||
void begin(uint32 baud); |
|||
void begin(uint32 baud,uint8_t config); |
|||
void end(); |
|||
int available(); |
|||
int read(); |
|||
int write(uint8_t); |
|||
inline void wifi_usart_irq(usart_reg_map *regs) { |
|||
/* Handling RXNEIE and TXEIE interrupts.
|
|||
* RXNE signifies availability of a byte in DR. |
|||
* |
|||
* See table 198 (sec 27.4, p809) in STM document RM0008 rev 15. |
|||
* We enable RXNEIE. |
|||
*/ |
|||
if ((regs->CR1 & USART_CR1_RXNEIE) && (regs->SR & USART_SR_RXNE)) { |
|||
#ifdef USART_SAFE_INSERT |
|||
/* If the buffer is full and the user defines USART_SAFE_INSERT,
|
|||
* ignore new bytes. */ |
|||
rb_safe_insert(this->usart_device->rb, (uint8)regs->DR); |
|||
#else |
|||
/* By default, push bytes around in the ring buffer. */ |
|||
rb_push_insert(this->usart_device->rb, (uint8)regs->DR); |
|||
#endif |
|||
} |
|||
/* TXE signifies readiness to send a byte to DR. */ |
|||
if ((regs->CR1 & USART_CR1_TXEIE) && (regs->SR & USART_SR_TXE)) { |
|||
if (!rb_is_empty(this->usart_device->wb)) |
|||
regs->DR=rb_remove(this->usart_device->wb); |
|||
else |
|||
regs->CR1 &= ~((uint32)USART_CR1_TXEIE); // disable TXEIE
|
|||
} |
|||
} |
|||
int wifi_rb_is_full(); |
|||
struct usart_dev *usart_device; |
|||
private: |
|||
uint8 tx_pin; |
|||
uint8 rx_pin; |
|||
}; |
File diff suppressed because it is too large
Loading…
Reference in new issue