Merge branch 'DiSlord_test_branch'

pull/4/head
erikkaashoek 6 years ago
commit 853aec4a84

@ -204,6 +204,11 @@ static char *ftoaS(char *p, float num, int precision) {
if (precision<0) if (precision<0)
precision=0; precision=0;
p=ftoa(p, num, precision); p=ftoa(p, num, precision);
// remove zeros at end
if (precision){
while (p[-1]=='0') p--;
if (p[-1]=='.') p--;
}
if (prefix) if (prefix)
*p++ = prefix; *p++ = prefix;
return p; return p;

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com * Copyright (c) 2019-2020, written by DiSlord dislordlive@gmail.com
* All rights reserved. * All rights reserved.
* *
* This is free software; you can redistribute it and/or modify * This is free software; you can redistribute it and/or modify
@ -21,8 +21,23 @@
#include "hal.h" #include "hal.h"
#include "nanovna.h" #include "nanovna.h"
// Allow enable DMA for read display data (some problem vs use in ST7796 in fast mode) #include "spi.h"
#define __USE_DISPLAY_DMA_RX__ // Allow enable DMA for read display data
//#define __USE_DISPLAY_DMA_RX__
// Pin macros for LCD
#define LCD_CS_LOW palClearPad(GPIOB, GPIOB_LCD_CS)
#define LCD_CS_HIGH palSetPad(GPIOB, GPIOB_LCD_CS)
#define LCD_RESET_ASSERT palClearPad(GPIOA, GPIOA_LCD_RESET)
#define LCD_RESET_NEGATE palSetPad(GPIOA, GPIOA_LCD_RESET)
#define LCD_DC_CMD palClearPad(GPIOB, GPIOB_LCD_CD)
#define LCD_DC_DATA palSetPad(GPIOB, GPIOB_LCD_CD)
#define LCD_SPI SPI1
// Set SPI bus speed for LCD
#define LCD_SPI_SPEED SPI_BR_DIV2
//Not define if need use some as Tx speed
//#define LCD_SPI_RX_SPEED SPI_BR_DIV4
uint16_t spi_buffer[SPI_BUFFER_SIZE]; uint16_t spi_buffer[SPI_BUFFER_SIZE];
// Default foreground & background colors // Default foreground & background colors
@ -135,85 +150,44 @@ uint16_t background_color = 0;
#define DISPLAY_ROTATION_180 (ILI9341_MADCTL_MX | ILI9341_MADCTL_MY \ #define DISPLAY_ROTATION_180 (ILI9341_MADCTL_MX | ILI9341_MADCTL_MY \
| ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR) | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR)
// //*****************************************************
// Pin macros // SPI DMA settings and data
// //*****************************************************
#define RESET_ASSERT palClearPad(GPIOA, 15)
#define RESET_NEGATE palSetPad(GPIOA, 15)
#define CS_LOW palClearPad(GPIOB, 6)
#define CS_HIGH palSetPad(GPIOB, 6)
#define DC_CMD palClearPad(GPIOB, 7)
#define DC_DATA palSetPad(GPIOB, 7)
//*****************************************************************************
//********************************** SPI bus **********************************
//*****************************************************************************
// STM32 SPI transfer mode:
// in 8 bit mode:
// if you write *(uint8_t*)(&SPI1->DR) = (uint8_t) data, then data send as << data
// if you write *(uint16_t*)(&SPI1->DR) =(uint16_t) data, then data send as << dataLoByte, after send dataHiByte
// in 16 bit mode
// if you write *(uint16_t*)(&SPI1->DR) =(uint16_t) data, then data send as << data
// SPI init in 8 bit mode
#define SPI_CR2_8BIT 0x0700
#define SPI_CR2_16BIT 0x0F00
// SPI bus activity macros
// The RXNE flag is set depending on the FRXTH bit value in the SPIx_CR2 register:
// • If FRXTH is set, RXNE goes high and stays high until the RXFIFO level is greater or equal to 1/4 (8-bit).
#define SPI_RX_IS_NOT_EMPTY (SPI1->SR&SPI_SR_RXNE)
#define SPI_RX_IS_EMPTY (((SPI1->SR&SPI_SR_RXNE) == 0))
// The TXE flag is set when transmission TXFIFO has enough space to store data to send.
// 0: Tx buffer not empty, bit is cleared automatically when the TXFIFO level becomes greater than 1/2
// 1: Tx buffer empty, flag goes high and stays high until the TXFIFO level is lower or equal to 1/2 of the FIFO depth
#define SPI_TX_IS_NOT_EMPTY (((SPI1->SR&(SPI_SR_TXE)) == 0))
#define SPI_TX_IS_EMPTY (SPI1->SR&SPI_SR_TXE)
// When BSY is set, it indicates that a data transfer is in progress on the SPI (the SPI bus is busy).
#define SPI_IS_BUSY (SPI1->SR & SPI_SR_BSY)
// SPI send data macros
#define SPI_WRITE_8BIT(data) *(__IO uint8_t*)(&SPI1->DR) = (uint8_t) data
#define SPI_WRITE_16BIT(data) SPI1->DR = data
// SPI read data macros
#define SPI_READ_DATA SPI1->DR
#ifdef __USE_DISPLAY_DMA__ #ifdef __USE_DISPLAY_DMA__
static const stm32_dma_stream_t *dmatx = static const stm32_dma_stream_t *dmatx =
STM32_DMA_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM); STM32_DMA_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM);
static uint32_t txdmamode = static const uint32_t txdmamode =
STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) // Select SPI1 Tx DMA STM32_DMA_CR_CHSEL(SPI1_TX_DMA_CHANNEL) // Select SPI1 Tx DMA
| STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) // Set priority | STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) // Set priority
| STM32_DMA_CR_DIR_M2P // Memory to Spi | STM32_DMA_CR_DIR_M2P; // Memory to Spi
| STM32_DMA_CR_DMEIE //
| STM32_DMA_CR_TEIE;
// Not handle interrupt
#if 0
static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags)
{ {
(void)spip; (void)spip;
(void)flags; (void)flags;
} }
#endif
#ifdef __USE_DISPLAY_DMA_RX__ #ifdef __USE_DISPLAY_DMA_RX__
static const stm32_dma_stream_t *dmarx = STM32_DMA_STREAM(STM32_SPI_SPI1_RX_DMA_STREAM); static const stm32_dma_stream_t *dmarx = STM32_DMA_STREAM(STM32_SPI_SPI1_RX_DMA_STREAM);
static uint32_t rxdmamode = STM32_DMA_CR_CHSEL(SPI1_RX_DMA_CHANNEL) static const uint32_t rxdmamode =
| STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) STM32_DMA_CR_CHSEL(SPI1_RX_DMA_CHANNEL) // Select SPI1 Rx DMA
| STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) // Set priority
| STM32_DMA_CR_TCIE | STM32_DMA_CR_DIR_P2M; // SPI to Memory
| STM32_DMA_CR_DMEIE
| STM32_DMA_CR_TEIE;
// Not handle interrupt
#if 0
static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags)
{ {
(void)spip; (void)spip;
(void)flags; (void)flags;
} }
#endif #endif
#endif
// Send prepared DMA data, and wait completion
static void dmaStreamFlush(uint32_t len) static void dmaStreamFlush(uint32_t len)
{ {
while (len) { while (len) {
@ -227,53 +201,129 @@ static void dmaStreamFlush(uint32_t len)
} }
#endif #endif
// SPI transmit byte to SPI (no wait complete transmit)
void spi_TxByte(uint8_t data) {
SPI_WRITE_8BIT(LCD_SPI, data);
}
// Transmit word to SPI bus (if SPI in 8 bit mode LSB send first!!!!!)
void spi_TxWord(uint16_t data) {
SPI_WRITE_16BIT(LCD_SPI, data);
}
// Transmit buffer to SPI bus (len should be > 0)
void spi_TxBuffer(uint8_t *buffer, uint16_t len) {
do {
while (SPI_TX_IS_NOT_EMPTY(LCD_SPI));
SPI_WRITE_8BIT(LCD_SPI, *buffer++);
}while(--len);
}
// Receive byte from SPI bus
uint8_t spi_RxByte(void) {
// Start RX clock (by sending data)
SPI_WRITE_8BIT(LCD_SPI, 0xFF);
while (SPI_RX_IS_EMPTY(LCD_SPI)||SPI_IS_BUSY(LCD_SPI));
return SPI_READ_8BIT(LCD_SPI);
}
// Receive buffer from SPI bus (len should be > 0)
void spi_RxBuffer(uint8_t *buffer, uint16_t len) {
do{
SPI_WRITE_8BIT(LCD_SPI, 0xFF);
while (SPI_RX_IS_EMPTY(LCD_SPI));
*buffer++ = SPI_READ_8BIT(LCD_SPI);
}while(--len);
}
void spi_DropRx(void){
// Drop Rx buffer after tx and wait tx complete
while (SPI_RX_IS_NOT_EMPTY(LCD_SPI)||SPI_IS_BUSY(LCD_SPI))
(void)SPI_READ_8BIT(LCD_SPI);
}
#ifdef __USE_DISPLAY_DMA__
// SPI receive byte buffer use DMA
void spi_DMATxBuffer(uint8_t *buffer, uint16_t len) {
dmaStreamSetMemory0(dmatx, buffer);
dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_MINC);
dmaStreamFlush(len);
}
#ifdef __USE_DISPLAY_DMA_RX__
// SPI transmit byte buffer use DMA
static void spi_DMARxBuffer(uint8_t *buffer, uint16_t len) {
uint8_t dummy_tx = 0xFF;
// Init Rx DMA buffer, size, mode (spi and mem data size is 8 bit)
dmaStreamSetMemory0(dmarx, buffer);
dmaStreamSetTransactionSize(dmarx, len);
dmaStreamSetMode(dmarx, rxdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_MINC);
// Init dummy Tx DMA (for rx clock), size, mode (spi and mem data size is 8 bit)
dmaStreamSetMemory0(dmatx, &dummy_tx);
dmaStreamSetTransactionSize(dmatx, len);
dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE);
// Skip SPI rx buffer
spi_DropRx();
// Start DMA exchange
dmaStreamEnable(dmarx);
dmaStreamEnable(dmatx);
// Wait DMA completion
dmaWaitCompletion(dmatx);
dmaWaitCompletion(dmarx);
}
#endif
#endif
static void spi_init(void) static void spi_init(void)
{ {
rccEnableSPI1(FALSE); rccEnableSPI1(FALSE);
SPI1->CR1 = 0; LCD_SPI->CR1 = 0;
SPI1->CR1 = SPI_CR1_MSTR // SPI is MASTER LCD_SPI->CR1 = SPI_CR1_MSTR // SPI is MASTER
| SPI_CR1_SSM // Software slave management (The external NSS pin is free for other application uses) | SPI_CR1_SSM // Software slave management (The external NSS pin is free for other application uses)
| SPI_CR1_SSI; // Internal slave select (This bit has an effect only when the SSM bit is set. Allow use NSS pin as I/O) | SPI_CR1_SSI // Internal slave select (This bit has an effect only when the SSM bit is set. Allow use NSS pin as I/O)
// | SPI_CR1_BR_1; // Baud rate control | LCD_SPI_SPEED // Baud rate control
// | SPI_CR1_CPHA // Clock Phase
SPI1->CR2 = SPI_CR2_8BIT // SPI data size, set to 8 bit // | SPI_CR1_CPOL // Clock Polarity
| SPI_CR2_FRXTH; // SPI_SR_RXNE generated every 8 bit data ;
// | SPI_CR2_SSOE; //
LCD_SPI->CR2 = SPI_CR2_8BIT // SPI data size, set to 8 bit
| SPI_CR2_FRXTH; // SPI_SR_RXNE generated every 8 bit data
// | SPI_CR2_SSOE; //
#ifdef __USE_DISPLAY_DMA__ #ifdef __USE_DISPLAY_DMA__
// Tx DMA init // Tx DMA init
dmaStreamAllocate(dmatx, STM32_SPI_SPI1_IRQ_PRIORITY, (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, NULL); dmaStreamAllocate(dmatx, STM32_SPI_SPI1_IRQ_PRIORITY, NULL, NULL);
dmaStreamSetPeripheral(dmatx, &SPI1->DR); dmaStreamSetPeripheral(dmatx, &LCD_SPI->DR);
SPI1->CR2|= SPI_CR2_TXDMAEN; // Tx DMA enable LCD_SPI->CR2|= SPI_CR2_TXDMAEN; // Tx DMA enable
#ifdef __USE_DISPLAY_DMA_RX__ #ifdef __USE_DISPLAY_DMA_RX__
// Rx DMA init // Rx DMA init
dmaStreamAllocate(dmarx, STM32_SPI_SPI1_IRQ_PRIORITY, (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, NULL); dmaStreamAllocate(dmarx, STM32_SPI_SPI1_IRQ_PRIORITY, NULL, NULL);
dmaStreamSetPeripheral(dmarx, &SPI1->DR); dmaStreamSetPeripheral(dmarx, &LCD_SPI->DR);
// Enable DMA on SPI // Enable DMA on SPI
SPI1->CR2|= SPI_CR2_RXDMAEN; // Rx DMA enable LCD_SPI->CR2|= SPI_CR2_RXDMAEN; // Rx DMA enable
#endif #endif
#endif #endif
SPI1->CR1|= SPI_CR1_SPE; //SPI enable LCD_SPI->CR1|= SPI_CR1_SPE; //SPI enable
} }
// Disable inline for this function // Disable inline for this function
static void __attribute__ ((noinline)) send_command(uint8_t cmd, uint8_t len, const uint8_t *data) static void send_command(uint8_t cmd, uint8_t len, const uint8_t *data)
{ {
CS_LOW; // Uncomment on low speed SPI (possible get here before previous tx complete)
//while (SPI_TX_IS_NOT_EMPTY); // while (SPI_IN_TX_RX);
DC_CMD; LCD_CS_LOW;
SPI_WRITE_8BIT(cmd); LCD_DC_CMD;
SPI_WRITE_8BIT(LCD_SPI, cmd);
// Need wait transfer complete and set data bit // Need wait transfer complete and set data bit
while (SPI_IS_BUSY) while (SPI_IN_TX_RX(LCD_SPI))
; ;
// Send command data (if need) // Send command data (if need)
DC_DATA; LCD_DC_DATA;
while (len-- > 0) { while (len-- > 0) {
while (SPI_TX_IS_NOT_EMPTY) while (SPI_TX_IS_NOT_EMPTY(LCD_SPI))
; ;
SPI_WRITE_8BIT(*data++); SPI_WRITE_8BIT(LCD_SPI, *data++);
} }
//CS_HIGH; //LCD_CS_HIGH;
} }
static const uint8_t ili9341_init_seq[] = { static const uint8_t ili9341_init_seq[] = {
@ -337,10 +387,10 @@ static const uint8_t ili9341_init_seq[] = {
void ili9341_init(void) void ili9341_init(void)
{ {
spi_init(); spi_init();
DC_DATA; LCD_DC_DATA;
RESET_ASSERT; LCD_RESET_ASSERT;
chThdSleepMilliseconds(10); chThdSleepMilliseconds(10);
RESET_NEGATE; LCD_RESET_NEGATE;
const uint8_t *p; const uint8_t *p;
for (p = ili9341_init_seq; *p; ) { for (p = ili9341_init_seq; *p; ) {
send_command(p[0], p[1], &p[2]); send_command(p[0], p[1], &p[2]);
@ -351,6 +401,8 @@ void ili9341_init(void)
void ili9341_bulk_8bit(int x, int y, int w, int h, uint16_t *palette) void ili9341_bulk_8bit(int x, int y, int w, int h, uint16_t *palette)
{ {
//uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) };
//uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) };
uint32_t xx = __REV16(x | ((x + w - 1) << 16)); uint32_t xx = __REV16(x | ((x + w - 1) << 16));
uint32_t yy = __REV16(y | ((y + h - 1) << 16)); uint32_t yy = __REV16(y | ((y + h - 1) << 16));
send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx); send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx);
@ -359,12 +411,8 @@ void ili9341_bulk_8bit(int x, int y, int w, int h, uint16_t *palette)
uint8_t *buf = (uint8_t *)spi_buffer; uint8_t *buf = (uint8_t *)spi_buffer;
int32_t len = w * h; int32_t len = w * h;
while (len-- > 0) { while (len-- > 0)
uint16_t color = palette[*buf++]; spi_TxWord(palette[*buf++]);
while (SPI_TX_IS_NOT_EMPTY)
;
SPI_WRITE_16BIT(color);
}
} }
#ifndef __USE_DISPLAY_DMA__ #ifndef __USE_DISPLAY_DMA__
@ -378,17 +426,14 @@ void ili9341_fill(int x, int y, int w, int h, uint16_t color)
send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy);
send_command(ILI9341_MEMORY_WRITE, 0, NULL); send_command(ILI9341_MEMORY_WRITE, 0, NULL);
int32_t len = w * h; int32_t len = w * h;
while (len-- > 0) { while (len-- > 0)
while (SPI_TX_IS_NOT_EMPTY) spi_TxWord(color);
;
SPI_WRITE_16BIT(color);
}
} }
void ili9341_bulk(int x, int y, int w, int h) void ili9341_bulk(int x, int y, int w, int h)
{ {
// uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) }; //uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) };
// uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) }; //uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) };
uint16_t *buf = spi_buffer; uint16_t *buf = spi_buffer;
uint32_t xx = __REV16(x | ((x + w - 1) << 16)); uint32_t xx = __REV16(x | ((x + w - 1) << 16));
uint32_t yy = __REV16(y | ((y + h - 1) << 16)); uint32_t yy = __REV16(y | ((y + h - 1) << 16));
@ -396,11 +441,8 @@ void ili9341_bulk(int x, int y, int w, int h)
send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy);
send_command(ILI9341_MEMORY_WRITE, 0, NULL); send_command(ILI9341_MEMORY_WRITE, 0, NULL);
int32_t len = w * h; int32_t len = w * h;
while (len-- > 0) { while (len-- > 0)
while (SPI_TX_IS_NOT_EMPTY) spi_TxWord(*buf++);
;
SPI_WRITE_16BIT(*buf++);
}
} }
#else #else
// //
@ -409,6 +451,8 @@ void ili9341_bulk(int x, int y, int w, int h)
// Fill region by some color // Fill region by some color
void ili9341_fill(int x, int y, int w, int h, uint16_t color) void ili9341_fill(int x, int y, int w, int h, uint16_t color)
{ {
//uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) };
//uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) };
uint32_t xx = __REV16(x | ((x + w - 1) << 16)); uint32_t xx = __REV16(x | ((x + w - 1) << 16));
uint32_t yy = __REV16(y | ((y + h - 1) << 16)); uint32_t yy = __REV16(y | ((y + h - 1) << 16));
send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx); send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx);
@ -438,75 +482,83 @@ void ili9341_bulk(int x, int y, int w, int h)
#endif #endif
#ifndef __USE_DISPLAY_DMA_RX__ #ifndef __USE_DISPLAY_DMA_RX__
static uint8_t ssp_sendrecvdata(void)
{
// Start RX clock (by sending data)
SPI_WRITE_8BIT(0);
while (SPI_RX_IS_EMPTY && SPI_IS_BUSY)
;
return SPI_READ_DATA;
}
void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out) void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out)
{ {
// uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) }; //uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) };
// uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) }; //uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) };
uint32_t xx = __REV16(x | ((x + w - 1) << 16)); uint32_t xx = __REV16(x | ((x + w - 1) << 16));
uint32_t yy = __REV16(y | ((y + h - 1) << 16)); uint32_t yy = __REV16(y | ((y + h - 1) << 16));
send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx); send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx);
send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy);
send_command(ILI9341_MEMORY_READ, 0, NULL); send_command(ILI9341_MEMORY_READ, 0, NULL);
// Skip data from rx buffer // Skip data from rx buffer
while (SPI_RX_IS_NOT_EMPTY) spi_DropRx();
(void) SPI_READ_DATA; // Set read speed (if need different)
#ifdef LCD_SPI_RX_SPEED
SPI_BR_SET(LCD_SPI, LCD_SPI_RX_SPEED);
#endif
// require 8bit dummy clock // require 8bit dummy clock
ssp_sendrecvdata(); spi_RxByte();
while (len-- > 0) { while (len-- > 0) {
uint8_t r, g, b;
// read data is always 18bit // read data is always 18bit
uint8_t r = ssp_sendrecvdata(); r = spi_RxByte();
uint8_t g = ssp_sendrecvdata(); g = spi_RxByte();
uint8_t b = ssp_sendrecvdata(); b = spi_RxByte();
*out++ = RGB565(r, g, b); *out++ = RGB565(r, g, b);
} }
CS_HIGH; // restore speed if need
#ifdef LCD_SPI_RX_SPEED
SPI_BR_SET(LCD_SPI, LCD_SPI_SPEED);
#endif
LCD_CS_HIGH;
} }
#else #else
// Copy screen data to buffer // Copy screen data to buffer
// Warning!!! buffer size must be greater then 3*len + 1 bytes // Warning!!! buffer size must be greater then 3*len + 1 bytes
void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out) void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out)
{ {
uint8_t dummy_tx = 0; uint16_t dummy_tx = 0;
uint8_t *rgbbuf = (uint8_t *)out; uint8_t *rgbbuf = (uint8_t *)out;
uint16_t data_size = len * 3 + 1; uint16_t data_size = len * 3;
//uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) };
//uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) };
uint32_t xx = __REV16(x | ((x + w - 1) << 16)); uint32_t xx = __REV16(x | ((x + w - 1) << 16));
uint32_t yy = __REV16(y | ((y + h - 1) << 16)); uint32_t yy = __REV16(y | ((y + h - 1) << 16));
send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx); send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t *)&xx);
send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t *)&yy); send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t *)&yy);
send_command(ILI9341_MEMORY_READ, 0, NULL); send_command(ILI9341_MEMORY_READ, 0, NULL);
// Skip SPI rx buffer
while (SPI_RX_IS_NOT_EMPTY) (void)SPI_READ_DATA;
// Init Rx DMA buffer, size, mode (spi and mem data size is 8 bit) // Init Rx DMA buffer, size, mode (spi and mem data size is 8 bit)
dmaStreamSetMemory0(dmarx, rgbbuf); dmaStreamSetMemory0(dmarx, rgbbuf);
dmaStreamSetTransactionSize(dmarx, data_size); dmaStreamSetTransactionSize(dmarx, data_size);
dmaStreamSetMode(dmarx, rxdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | dmaStreamSetMode(dmarx, rxdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_MINC);
STM32_DMA_CR_MINC);
// Init dummy Tx DMA (for rx clock), size, mode (spi and mem data size is 8 bit) // Init dummy Tx DMA (for rx clock), size, mode (spi and mem data size is 8 bit)
dmaStreamSetMemory0(dmatx, &dummy_tx); dmaStreamSetMemory0(dmatx, &dummy_tx);
dmaStreamSetTransactionSize(dmatx, data_size); dmaStreamSetTransactionSize(dmatx, data_size);
dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE); dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE);
// Skip SPI rx buffer
spi_DropRx();
// Set read speed (if need different)
#ifdef LCD_SPI_RX_SPEED
SPI_BR_SET(LCD_SPI, LCD_SPI_RX_SPEED);
#endif
// require 8bit dummy clock
spi_RxByte();
// Start DMA exchange // Start DMA exchange
dmaStreamEnable(dmarx); dmaStreamEnable(dmarx);
dmaStreamEnable(dmatx); dmaStreamEnable(dmatx);
// Wait DMA completion // Wait DMA completion
dmaWaitCompletion(dmatx); dmaWaitCompletion(dmatx);
dmaWaitCompletion(dmarx); dmaWaitCompletion(dmarx);
CS_HIGH; // restore speed if need
#ifdef LCD_SPI_RX_SPEED
SPI_BR_SET(LCD_SPI, LCD_SPI_SPEED);
#endif
LCD_CS_HIGH;
// Parce recived data // Parce recived data
// Skip dummy 8-bit read
rgbbuf++;
while (len-- > 0) { while (len-- > 0) {
uint8_t r, g, b; uint8_t r, g, b;
// read data is always 18bit // read data is always 18bit
@ -519,7 +571,7 @@ void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out)
} }
#endif #endif
void ili9341_clear_screen(void) void ili9341_clear_screen(void)
{ {
ili9341_fill(0, 0, ILI9341_WIDTH, ILI9341_HEIGHT, background_color); ili9341_fill(0, 0, ILI9341_WIDTH, ILI9341_HEIGHT, background_color);
} }
@ -546,7 +598,7 @@ void ili9341_set_rotation(uint8_t r)
} }
void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
const uint8_t *bitmap) const uint8_t *bitmap)
{ {
uint16_t *buf = spi_buffer; uint16_t *buf = spi_buffer;
for (uint16_t c = 0; c < height; c++) { for (uint16_t c = 0; c < height; c++) {
@ -560,7 +612,7 @@ void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height
} }
void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
const uint16_t *bitmap) const uint16_t *bitmap)
{ {
uint16_t *buf = spi_buffer; uint16_t *buf = spi_buffer;
for (uint16_t c = 0; c < height; c++) { for (uint16_t c = 0; c < height; c++) {
@ -573,12 +625,6 @@ void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t heigh
ili9341_bulk(x, y, width, height); ili9341_bulk(x, y, width, height);
} }
int ili9341_size = 1;
void ili9341_charsize(int s)
{
ili9341_size = s;
}
void ili9341_drawchar(uint8_t ch, int x, int y) void ili9341_drawchar(uint8_t ch, int x, int y)
{ {
blit8BitWidthBitmap(x, y, FONT_GET_WIDTH(ch), FONT_GET_HEIGHT, FONT_GET_DATA(ch)); blit8BitWidthBitmap(x, y, FONT_GET_WIDTH(ch), FONT_GET_HEIGHT, FONT_GET_DATA(ch));

@ -165,7 +165,7 @@ static THD_FUNCTION(Thread1, arg)
else else
redraw_request |= REDRAW_CAL_STATUS | REDRAW_AREA | REDRAW_FREQUENCY; redraw_request |= REDRAW_CAL_STATUS | REDRAW_AREA | REDRAW_FREQUENCY;
} }
continue; // continue;
} }
// START_PROFILE // START_PROFILE
// Process UI inputs // Process UI inputs
@ -2310,7 +2310,7 @@ static const VNAShellCommand commands[] =
{"save" , cmd_save , 0}, {"save" , cmd_save , 0},
{"recall" , cmd_recall , CMD_WAIT_MUTEX}, {"recall" , cmd_recall , CMD_WAIT_MUTEX},
#endif #endif
{"trace" , cmd_trace , 0}, {"trace" , cmd_trace , CMD_WAIT_MUTEX},
{"trigger" , cmd_trigger , 0}, {"trigger" , cmd_trigger , 0},
{"marker" , cmd_marker , 0}, {"marker" , cmd_marker , 0},
#ifdef __VNA__ #ifdef __VNA__
@ -2729,12 +2729,12 @@ int main(void)
redraw_frame(); redraw_frame();
set_mode(M_HIGH); set_mode(M_HIGH);
set_sweep_frequency(ST_STOP, (uint32_t) 30000000); set_sweep_frequency(ST_STOP, (uint32_t) 30000000);
sweep(true); sweep(false);
osalThreadSleepMilliseconds(100); osalThreadSleepMilliseconds(100);
set_mode(M_LOW); set_mode(M_LOW);
set_sweep_frequency(ST_STOP, (uint32_t) 4000000); set_sweep_frequency(ST_STOP, (uint32_t) 4000000);
sweep(true); sweep(false);
set_sweep_frequency(ST_STOP, (uint32_t) 350000000); set_sweep_frequency(ST_STOP, (uint32_t) 350000000);
set_refer_output(-1); set_refer_output(-1);
@ -2782,7 +2782,6 @@ void HardFault_Handler(void)
__asm volatile("mrs %0, psp \n\t" : "=r"(sp)); __asm volatile("mrs %0, psp \n\t" : "=r"(sp));
hard_fault_handler_c(sp); hard_fault_handler_c(sp);
} }
#define FONT_STR_HEIGHT 7
void hard_fault_handler_c(uint32_t *sp) void hard_fault_handler_c(uint32_t *sp)
{ {

@ -304,7 +304,7 @@ extern uint16_t _grid_y;
#define AREA_WIDTH_NORMAL (CELLOFFSETX + WIDTH + 1) #define AREA_WIDTH_NORMAL (CELLOFFSETX + WIDTH + 1)
#define AREA_HEIGHT_NORMAL ( HEIGHT + 1) #define AREA_HEIGHT_NORMAL ( HEIGHT + 1)
#define GRID_X_TEXT (AREA_WIDTH_NORMAL - 6*5) #define GRID_X_TEXT (AREA_WIDTH_NORMAL - 7*5)
// Smith/polar chart // Smith/polar chart
#define P_CENTER_X (CELLOFFSETX + WIDTH/2) #define P_CENTER_X (CELLOFFSETX + WIDTH/2)

@ -1958,7 +1958,7 @@ static void cell_grid_line_info(int x0, int y0)
for (int i = 0; i < NGRIDY; i++){ for (int i = 0; i < NGRIDY; i++){
if (ypos >= CELLHEIGHT) break; if (ypos >= CELLHEIGHT) break;
if (ypos >= -FONT_GET_HEIGHT){ if (ypos >= -FONT_GET_HEIGHT){
plot_printf(buf, sizeof buf, "% 6.2F", ref); plot_printf(buf, sizeof buf, "% 7.3F", ref);
cell_drawstring(buf, xpos, ypos); cell_drawstring(buf, xpos, ypos);
} }
ypos+=GRIDY; ypos+=GRIDY;

@ -1386,7 +1386,16 @@ pureRSSI_t perform(bool break_on_operation, int i, uint32_t f, int tracking)
setting.actual_sweep_time_us = calc_min_sweep_time_us(); setting.actual_sweep_time_us = calc_min_sweep_time_us();
// Change actual sweep time as user input if it greater minimum // Change actual sweep time as user input if it greater minimum
// And set start delays for 1 run // And set start delays for 1 run
if (setting.sweep_time_us > setting.actual_sweep_time_us){ // manually set delay, for better sync
if (setting.sweep_time_us < 2.5 * ONE_MS_TIME){
setting.additional_step_delay_us = 0;
setting.sweep_time_us = 0; // set minimum
}
else if (setting.sweep_time_us <= 3 * ONE_MS_TIME){
setting.additional_step_delay_us = 1;
setting.sweep_time_us = 3000;
}
else if (setting.sweep_time_us > setting.actual_sweep_time_us){
setting.additional_step_delay_us = (setting.sweep_time_us - setting.actual_sweep_time_us)/(sweep_points); setting.additional_step_delay_us = (setting.sweep_time_us - setting.actual_sweep_time_us)/(sweep_points);
setting.actual_sweep_time_us = setting.sweep_time_us; setting.actual_sweep_time_us = setting.sweep_time_us;
} }
@ -1402,17 +1411,7 @@ pureRSSI_t perform(bool break_on_operation, int i, uint32_t f, int tracking)
+ get_attenuation() + get_attenuation()
- setting.offset); - setting.offset);
} }
#if 0
// manually set delay, for better sync
if (setting.sweep_time_us < 2.5 * ONE_MS_TIME){
setting.additional_step_delay_us = 0;
setting.sweep_time_us = 0;
}
else if (setting.sweep_time_us <= 3 * ONE_MS_TIME){
setting.additional_step_delay_us = 1;
setting.sweep_time_us = 3000;
}
#endif
// if (MODE_OUTPUT(setting.mode) && setting.additional_step_delay_us < 500) // Minimum wait time to prevent LO from lockup during output frequency sweep // if (MODE_OUTPUT(setting.mode) && setting.additional_step_delay_us < 500) // Minimum wait time to prevent LO from lockup during output frequency sweep
// setting.additional_step_delay_us = 500; // setting.additional_step_delay_us = 500;
// Update grid and status after // Update grid and status after
@ -2331,7 +2330,7 @@ void draw_cal_status(void)
if (rounding) if (rounding)
plot_printf(buf, BLEN, "%+4d", (int)yMax); plot_printf(buf, BLEN, "%+4d", (int)yMax);
else else
plot_printf(buf, BLEN, "%+.3F", (yMax/setting.unit_scale)); plot_printf(buf, BLEN, "%+4.3F", (yMax/setting.unit_scale));
if (level_is_calibrated()) { if (level_is_calibrated()) {
if (setting.auto_reflevel) if (setting.auto_reflevel)
@ -2465,10 +2464,10 @@ void draw_cal_status(void)
ili9341_drawstring(buf, x, y); ili9341_drawstring(buf, x, y);
y += YSTEP; y += YSTEP;
plot_printf(buf, BLEN, "%.3Fs", (float)setting.sweep_time_us/ONE_SECOND_TIME); plot_printf(buf, BLEN, "%5.3Fs", (float)setting.sweep_time_us/ONE_SECOND_TIME);
ili9341_drawstring(buf, x, y); ili9341_drawstring(buf, x, y);
y += YSTEP; y += YSTEP;
plot_printf(buf, BLEN, "%.3Fs", (float)setting.actual_sweep_time_us/ONE_SECOND_TIME); plot_printf(buf, BLEN, "%5.3Fs", (float)setting.actual_sweep_time_us/ONE_SECOND_TIME);
ili9341_drawstring(buf, x, y); ili9341_drawstring(buf, x, y);
#if 1 #if 1
y += YSTEP; y += YSTEP;
@ -2478,10 +2477,10 @@ void draw_cal_status(void)
// if (t < setting.sweep_time_us) // if (t < setting.sweep_time_us)
// t = setting.sweep_time_us; // t = setting.sweep_time_us;
// setting.actual_sweep_time_us = t; // setting.actual_sweep_time_us = t;
plot_printf(buf, BLEN, "%.3Fs", (float)t/ONE_SECOND_TIME); plot_printf(buf, BLEN, "%5.3Fs", (float)t/ONE_SECOND_TIME);
ili9341_drawstring(buf, x, y); ili9341_drawstring(buf, x, y);
y += YSTEP; y += YSTEP;
plot_printf(buf, BLEN, "%.3Fs", (float)setting.additional_step_delay_us/ONE_SECOND_TIME); plot_printf(buf, BLEN, "%5.3Fs", (float)setting.additional_step_delay_us/ONE_SECOND_TIME);
ili9341_drawstring(buf, x, y); ili9341_drawstring(buf, x, y);
#endif #endif
@ -2588,11 +2587,11 @@ void draw_cal_status(void)
// ili9341_set_background(DEFAULT_BG_COLOR); // ili9341_set_background(DEFAULT_BG_COLOR);
// Bottom level // Bottom level
y = area_height - 7 + OFFSETY; y = area_height - 8 + OFFSETY;
if (rounding) if (rounding)
plot_printf(buf, BLEN, "%4d", (int)(yMax - setting.scale * NGRIDY)); plot_printf(buf, BLEN, "%4d", (int)(yMax - setting.scale * NGRIDY));
else else
plot_printf(buf, BLEN, "%.3F", ((yMax - setting.scale * NGRIDY)/setting.unit_scale)); plot_printf(buf, BLEN, "%+4.3F", ((yMax - setting.scale * NGRIDY)/setting.unit_scale));
// buf[5]=0; // buf[5]=0;
if (level_is_calibrated()) if (level_is_calibrated())
if (setting.auto_reflevel) if (setting.auto_reflevel)

80
spi.h

@ -0,0 +1,80 @@
/*
* Copyright (c) 2019-2020, Dmitry Slepynin (DiSlord) dislordlive@gmail.com
* All rights reserved.
*
* This 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, or (at your option)
* any later version.
*
* The software 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 GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
//*****************************************************************************
//********************************** SPI1 bus *********************************
//*****************************************************************************
// STM32 SPI transfer mode:
// in 8 bit mode:
// if you write *(uint8_t*)(&SPI1->DR) = (uint8_t) data, then data send as << data
// if you write *(uint16_t*)(&SPI1->DR) =(uint16_t) data, then data send as << dataLoByte, after send dataHiByte
// in 16 bit mode
// if you write *(uint16_t*)(&SPI1->DR) =(uint16_t) data, then data send as << data
// SPI init in 8 bit mode
#define SPI_CR2_8BIT 0x0700
#define SPI_CR2_16BIT 0x0F00
//*****************************************************
// SPI bus baud rate (PPL/BR_DIV)
//*****************************************************
#define SPI_BR_DIV2 (0x00000000U)
#define SPI_BR_DIV4 (SPI_CR1_BR_0)
#define SPI_BR_DIV8 (SPI_CR1_BR_1)
#define SPI_BR_DIV16 (SPI_CR1_BR_1|SPI_CR1_BR_0)
#define SPI_BR_DIV32 (SPI_CR1_BR_2)
#define SPI_BR_DIV64 (SPI_CR1_BR_2|SPI_CR1_BR_0)
#define SPI_BR_DIV128 (SPI_CR1_BR_2|SPI_CR1_BR_1)
#define SPI_BR_DIV256 (SPI_CR1_BR_2|SPI_CR1_BR_1|SPI_CR1_BR_0)
#define SPI_BR_SET(spi, br) (spi->CR1 = (spi->CR1& ~(SPI_CR1_BR))|br)
//*****************************************************
// SPI bus activity macros
//*****************************************************
// The RXNE flag is set depending on the FRXTH bit value in the SPIx_CR2 register:
// • If FRXTH is set, RXNE goes high and stays high until the RXFIFO level is greater or equal to 1/4 (8-bit).
#define SPI_RX_IS_NOT_EMPTY(spi) (spi->SR&SPI_SR_RXNE)
#define SPI_RX_IS_EMPTY(spi) (((spi->SR&SPI_SR_RXNE) == 0))
// The TXE flag is set when transmission TXFIFO has enough space to store data to send.
// 0: Tx buffer not empty, bit is cleared automatically when the TXFIFO level becomes greater than 1/2
// 1: Tx buffer empty, flag goes high and stays high until the TXFIFO level is lower or equal to 1/2 of the FIFO depth
#define SPI_TX_IS_NOT_EMPTY(spi) (((spi->SR&(SPI_SR_TXE)) == 0))
#define SPI_TX_IS_EMPTY(spi) (spi->SR&SPI_SR_TXE)
// When BSY is set, it indicates that a data transfer is in progress on the SPI (the SPI bus is busy).
#define SPI_IS_BUSY(spi) (spi->SR & SPI_SR_BSY)
// Tx or Rx in process
#define SPI_IN_TX_RX(spi) ((spi->SR & (SPI_SR_TXE | SPI_SR_RXNE)) == 0 || SPI_IS_BUSY(spi))
//*****************************************************
// SPI send data macros
//*****************************************************
#define SPI_WRITE_8BIT(spi, data) *(__IO uint8_t*)(&spi->DR) = (uint8_t) data
#define SPI_WRITE_16BIT(spi, data) *(__IO uint16_t*)(&spi->DR) = (uint16_t) data
//*****************************************************
// SPI read data macros
//*****************************************************
#define SPI_READ_8BIT(spi) *(__IO uint8_t*)(&spi->DR)
#define SPI_READ_16BIT(spi) *(__IO uint16_t*)(&spi->DR)
Loading…
Cancel
Save

Powered by TurnKey Linux.