Yes, but I'm a Marlin fanboy ! Such a fanboy that I never installed Klipper !
This project is a challenge. Still have to learn SPI on RasPi, OctoPrint development, and come back to STM32 for bitmaps over SPI. Months of fun.
Most of all, I'm used to Marlin, and when I use my printer, it has to do what I need immediatly. It's a machine tool, as are my lathes, my milling machine, or my bandsaw. The printer works with Marlin, and I'm happy with Marlin.
I would probably have tested Klipper if I had a fast delta. But it's a cartesian.
The cleaned code :
The decoding function now takes 30µs instead of 480µs.
Code: Select all
#include <SPI.h>
#define __SERIAL_DEBUG
#define BAUD_RATE 250000
#define GFX_PAGE_COUNT 8
#define GFX_LINES_PER_PAGE 8
#define GFX_CMD_SIZE 3
#define GFX_PAGE_SIZE 128
#define SPI_PAGE_SIZE (GFX_CMD_SIZE + GFX_PAGE_SIZE)
#define SPI_FRAME_SIZE (GFX_PAGE_COUNT * SPI_PAGE_SIZE)
#define DMA_BUFFER_SIZE (2 * SPI_FRAME_SIZE)
volatile uint8_t rx_buffer[DMA_BUFFER_SIZE] = { 0 };
volatile uint8_t bitmap[GFX_PAGE_COUNT][GFX_PAGE_SIZE] = { 0 };
volatile bool dma_transfer_complete = false;
void rxDMAirq(void)
{
dma_irq_cause cause = dma_get_irq_cause(DMA1, DMA_CH2);
if (cause == DMA_TRANSFER_COMPLETE)
{
dma_transfer_complete = true;
return;
}
#ifdef __SERIAL_DEBUG
Serial.print("rxDMAirq error : ");
Serial.println(cause);
#endif
}
bool rebuildBitmap()
{
for (int i = 0; i < GFX_PAGE_COUNT; i++)
{
uint8_t* pRxBuf = (uint8_t*)rx_buffer + SPI_FRAME_SIZE + i * SPI_PAGE_SIZE;
uint16_t cmd = *(uint16_t*)pRxBuf;
uint8_t pageNum = *(uint8_t*)(pRxBuf + 2);
if(cmd != 0x10 || pageNum != i + 0xB0)
return false;
memcpy((uint8_t*)&bitmap + i * GFX_PAGE_SIZE, pRxBuf + GFX_CMD_SIZE, GFX_PAGE_SIZE);
}
return true;
}
void setup()
{
#ifdef __SERIAL_DEBUG
Serial.begin(BAUD_RATE);
#endif
delay(100);
setupSPI();
setupDMA();
}
void setupSPI(void)
{
pinMode(BOARD_SPI_DEFAULT_SS, INPUT);
SPI.setModule(1);
SPISettings spiSettings(0, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT);
SPI.beginTransactionSlave(spiSettings);
spi_rx_reg(SPI.dev());
}
void setupDMA(void)
{
dma_init(DMA1);
spi_rx_dma_disable(SPI.dev());
dma_disable(DMA1, DMA_CH2);
dma_detach_interrupt(DMA1, DMA_CH2);
dma_tube_config rx_tube_cfg =
{
&SPI1->regs->DR,
DMA_SIZE_8BITS,
&rx_buffer,
DMA_SIZE_8BITS,
DMA_BUFFER_SIZE,
DMA_CFG_DST_INC |
DMA_CFG_CIRC |
DMA_CFG_CMPLT_IE |
DMA_CCR_PL_VERY_HIGH,
0,
DMA_REQ_SRC_SPI1_RX
};
int ret_rx = dma_tube_cfg(DMA1, DMA_CH2, &rx_tube_cfg);
if (ret_rx != DMA_TUBE_CFG_SUCCESS)
{
while (1)
{
#ifdef __SERIAL_DEBUG
Serial.print("Rx DMA configuration error: ");
Serial.println(ret_rx, HEX);
Serial.println("Reset is needed!");
delay(100);
#else
#endif
}
}
spi_rx_reg(SPI.dev());
dma_attach_interrupt(DMA1, DMA_CH2, rxDMAirq);
dma_enable(DMA1, DMA_CH2);
spi_rx_dma_enable(SPI.dev());
}
void loop()
{
if (dma_transfer_complete)
{
#ifdef __SERIAL_DEBUG
if (rebuildBitmap())
printFrame();
#else
rebuildBitmap();
#endif
dma_transfer_complete = false;
}
delay(500);
}
#ifdef __SERIAL_DEBUG
void printFrame()
{
for (int page = 0; page < 8; page++)
{
for (int line = 0; line < GFX_LINES_PER_PAGE; line++)
{
for (int col = 0; col < GFX_PAGE_SIZE; col++)
{
uint8_t val = bitmap[page][col];
if (val & (1 << line))
Serial.print('#');
else
Serial.print(' ');
}
Serial.println();
}
}
for (int i = 0; i < 128; i++)
Serial.print('X');
Serial.println();
}
#endif