diff --git a/adc.c b/adc.c index 24862105..53ede93e 100644 --- a/adc.c +++ b/adc.c @@ -79,20 +79,23 @@ uint16_t adc_single_read(uint32_t chsel) int16_t adc_vbat_read(void) { +// 13.9 Temperature sensor and internal reference voltage +// VREFINT_CAL calibrated on 3.3V, need get value in mV #define ADC_FULL_SCALE 3300 #define VREFINT_CAL (*((uint16_t*)0x1FFFF7BA)) adc_stop(); - float vbat = 0; - float vrefint = 0; ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_VBATEN; // VREFINT == ADC_IN17 - vrefint = adc_single_read(ADC_CHSELR_CHSEL17); + uint32_t vrefint = adc_single_read(ADC_CHSELR_CHSEL17); // VBAT == ADC_IN18 // VBATEN enables resiter devider circuit. It consume vbat power. - vbat = adc_single_read(ADC_CHSELR_CHSEL18); + uint32_t vbat = adc_single_read(ADC_CHSELR_CHSEL18); ADC->CCR &= ~(ADC_CCR_VREFEN | ADC_CCR_VBATEN); touch_start_watchdog(); - uint16_t vbat_raw = (ADC_FULL_SCALE * VREFINT_CAL * vbat * 2 / (vrefint * ((1<<12)-1))); + // vbat_raw = (3300 * 2 * vbat / 4095) * (VREFINT_CAL / vrefint) + // uint16_t vbat_raw = (ADC_FULL_SCALE * VREFINT_CAL * (float)vbat * 2 / (vrefint * ((1<<12)-1))); + // For speed divide not on 4095, divide on 4096, get little error, but no matter + uint16_t vbat_raw = ((ADC_FULL_SCALE * 2 * vbat)>>12) * VREFINT_CAL / vrefint; if (vbat_raw < 100) { // maybe D2 is not installed return -1; diff --git a/chconf.h b/chconf.h index 5e5ce40f..fd54b74d 100644 --- a/chconf.h +++ b/chconf.h @@ -183,7 +183,7 @@ * * @note The default is @p TRUE. */ -#define CH_CFG_USE_MUTEXES TRUE +#define CH_CFG_USE_MUTEXES FALSE /** * @brief Enables recursive behavior on mutexes. diff --git a/fft.h b/fft.h index 0c367b72..dbaa32f5 100644 --- a/fft.h +++ b/fft.h @@ -68,8 +68,8 @@ static void fft256(float array[][2], const uint8_t dir) { uint16_t j, k; for (j = i, k = 0; j < i + halfsize; j++, k += tablestep) { uint16_t l = j + halfsize; - float tpre = array[l][real] * cos(2 * M_PI * k / 256) + array[l][imag] * sin(2 * M_PI * k / 256); - float tpim = -array[l][real] * sin(2 * M_PI * k / 256) + array[l][imag] * cos(2 * M_PI * k / 256); + float tpre = array[l][real] * cos(2 * VNA_PI * k / 256) + array[l][imag] * sin(2 * VNA_PI * k / 256); + float tpim = -array[l][real] * sin(2 * VNA_PI * k / 256) + array[l][imag] * cos(2 * VNA_PI * k / 256); array[l][real] = array[j][real] - tpre; array[l][imag] = array[j][imag] - tpim; array[j][real] += tpre; diff --git a/ili9341.c b/ili9341.c index 3c7568b8..a66fc9ab 100644 --- a/ili9341.c +++ b/ili9341.c @@ -23,97 +23,97 @@ uint16_t spi_buffer[SPI_BUFFER_SIZE]; // Default foreground & background colors -uint16_t foreground_color=DEFAULT_FG_COLOR; -uint16_t background_color=DEFAULT_BG_COLOR; +uint16_t foreground_color=0; +uint16_t background_color=0; // Display width and height definition -#define ILI9341_WIDTH 320 -#define ILI9341_HEIGHT 240 +#define ILI9341_WIDTH 320 +#define ILI9341_HEIGHT 240 // Display commands list -#define ILI9341_NOP 0x00 -#define ILI9341_SOFTWARE_RESET 0x01 -#define ILI9341_READ_IDENTIFICATION 0x04 -#define ILI9341_READ_STATUS 0x09 -#define ILI9341_READ_POWER_MODE 0x0A -#define ILI9341_READ_MADCTL 0x0B -#define ILI9341_READ_PIXEL_FORMAT 0x0C -#define ILI9341_READ_IMAGE_FORMAT 0x0D -#define ILI9341_READ_SIGNAL_MODE 0x0E -#define ILI9341_READ_SELF_DIAGNOSTIC 0x0F -#define ILI9341_SLEEP_IN 0x10 -#define ILI9341_SLEEP_OUT 0x11 -#define ILI9341_PARTIAL_MODE_ON 0x12 -#define ILI9341_NORMAL_DISPLAY_MODE_ON 0x13 -#define ILI9341_INVERSION_OFF 0x20 -#define ILI9341_INVERSION_ON 0x21 -#define ILI9341_GAMMA_SET 0x26 -#define ILI9341_DISPLAY_OFF 0x28 -#define ILI9341_DISPLAY_ON 0x29 -#define ILI9341_COLUMN_ADDRESS_SET 0x2A -#define ILI9341_PAGE_ADDRESS_SET 0x2B -#define ILI9341_MEMORY_WRITE 0x2C -#define ILI9341_COLOR_SET 0x2D -#define ILI9341_MEMORY_READ 0x2E -#define ILI9341_PARTIAL_AREA 0x30 -#define ILI9341_VERTICAL_SCROLLING_DEF 0x33 -#define ILI9341_TEARING_LINE_OFF 0x34 -#define ILI9341_TEARING_LINE_ON 0x35 -#define ILI9341_MEMORY_ACCESS_CONTROL 0x36 -#define ILI9341_VERTICAL_SCROLLING 0x37 -#define ILI9341_IDLE_MODE_OFF 0x38 -#define ILI9341_IDLE_MODE_ON 0x39 -#define ILI9341_PIXEL_FORMAT_SET 0x3A -#define ILI9341_WRITE_MEMORY_CONTINUE 0x3C -#define ILI9341_READ_MEMORY_CONTINUE 0x3E -#define ILI9341_SET_TEAR_SCANLINE 0x44 -#define ILI9341_GET_SCANLINE 0x45 -#define ILI9341_WRITE_BRIGHTNESS 0x51 -#define ILI9341_READ_BRIGHTNESS 0x52 -#define ILI9341_WRITE_CTRL_DISPLAY 0x53 -#define ILI9341_READ_CTRL_DISPLAY 0x54 -#define ILI9341_WRITE_CA_BRIGHTNESS 0x55 -#define ILI9341_READ_CA_BRIGHTNESS 0x56 -#define ILI9341_WRITE_CA_MIN_BRIGHTNESS 0x5E -#define ILI9341_READ_CA_MIN_BRIGHTNESS 0x5F -#define ILI9341_READ_ID1 0xDA -#define ILI9341_READ_ID2 0xDB -#define ILI9341_READ_ID3 0xDC -#define ILI9341_RGB_INTERFACE_CONTROL 0xB0 -#define ILI9341_FRAME_RATE_CONTROL_1 0xB1 -#define ILI9341_FRAME_RATE_CONTROL_2 0xB2 -#define ILI9341_FRAME_RATE_CONTROL_3 0xB3 -#define ILI9341_DISPLAY_INVERSION_CONTROL 0xB4 -#define ILI9341_BLANKING_PORCH_CONTROL 0xB5 -#define ILI9341_DISPLAY_FUNCTION_CONTROL 0xB6 -#define ILI9341_ENTRY_MODE_SET 0xB7 -#define ILI9341_BACKLIGHT_CONTROL_1 0xB8 -#define ILI9341_BACKLIGHT_CONTROL_2 0xB9 -#define ILI9341_BACKLIGHT_CONTROL_3 0xBA -#define ILI9341_BACKLIGHT_CONTROL_4 0xBB -#define ILI9341_BACKLIGHT_CONTROL_5 0xBC -#define ILI9341_BACKLIGHT_CONTROL_7 0xBE -#define ILI9341_BACKLIGHT_CONTROL_8 0xBF -#define ILI9341_POWER_CONTROL_1 0xC0 -#define ILI9341_POWER_CONTROL_2 0xC1 -#define ILI9341_VCOM_CONTROL_1 0xC5 -#define ILI9341_VCOM_CONTROL_2 0xC7 -#define ILI9341_POWERA 0xCB -#define ILI9341_POWERB 0xCF -#define ILI9341_NV_MEMORY_WRITE 0xD0 -#define ILI9341_NV_PROTECTION_KEY 0xD1 -#define ILI9341_NV_STATUS_READ 0xD2 -#define ILI9341_READ_ID4 0xD3 -#define ILI9341_POSITIVE_GAMMA_CORRECTION 0xE0 -#define ILI9341_NEGATIVE_GAMMA_CORRECTION 0xE1 -#define ILI9341_DIGITAL_GAMMA_CONTROL_1 0xE2 -#define ILI9341_DIGITAL_GAMMA_CONTROL_2 0xE3 -#define ILI9341_DTCA 0xE8 -#define ILI9341_DTCB 0xEA -#define ILI9341_POWER_SEQ 0xED -#define ILI9341_3GAMMA_EN 0xF2 -#define ILI9341_INTERFACE_CONTROL 0xF6 -#define ILI9341_PUMP_RATIO_CONTROL 0xF7 +#define ILI9341_NOP 0x00 +#define ILI9341_SOFTWARE_RESET 0x01 +#define ILI9341_READ_IDENTIFICATION 0x04 +#define ILI9341_READ_STATUS 0x09 +#define ILI9341_READ_POWER_MODE 0x0A +#define ILI9341_READ_MADCTL 0x0B +#define ILI9341_READ_PIXEL_FORMAT 0x0C +#define ILI9341_READ_IMAGE_FORMAT 0x0D +#define ILI9341_READ_SIGNAL_MODE 0x0E +#define ILI9341_READ_SELF_DIAGNOSTIC 0x0F +#define ILI9341_SLEEP_IN 0x10 +#define ILI9341_SLEEP_OUT 0x11 +#define ILI9341_PARTIAL_MODE_ON 0x12 +#define ILI9341_NORMAL_DISPLAY_MODE_ON 0x13 +#define ILI9341_INVERSION_OFF 0x20 +#define ILI9341_INVERSION_ON 0x21 +#define ILI9341_GAMMA_SET 0x26 +#define ILI9341_DISPLAY_OFF 0x28 +#define ILI9341_DISPLAY_ON 0x29 +#define ILI9341_COLUMN_ADDRESS_SET 0x2A +#define ILI9341_PAGE_ADDRESS_SET 0x2B +#define ILI9341_MEMORY_WRITE 0x2C +#define ILI9341_COLOR_SET 0x2D +#define ILI9341_MEMORY_READ 0x2E +#define ILI9341_PARTIAL_AREA 0x30 +#define ILI9341_VERTICAL_SCROLLING_DEF 0x33 +#define ILI9341_TEARING_LINE_OFF 0x34 +#define ILI9341_TEARING_LINE_ON 0x35 +#define ILI9341_MEMORY_ACCESS_CONTROL 0x36 +#define ILI9341_VERTICAL_SCROLLING 0x37 +#define ILI9341_IDLE_MODE_OFF 0x38 +#define ILI9341_IDLE_MODE_ON 0x39 +#define ILI9341_PIXEL_FORMAT_SET 0x3A +#define ILI9341_WRITE_MEMORY_CONTINUE 0x3C +#define ILI9341_READ_MEMORY_CONTINUE 0x3E +#define ILI9341_SET_TEAR_SCANLINE 0x44 +#define ILI9341_GET_SCANLINE 0x45 +#define ILI9341_WRITE_BRIGHTNESS 0x51 +#define ILI9341_READ_BRIGHTNESS 0x52 +#define ILI9341_WRITE_CTRL_DISPLAY 0x53 +#define ILI9341_READ_CTRL_DISPLAY 0x54 +#define ILI9341_WRITE_CA_BRIGHTNESS 0x55 +#define ILI9341_READ_CA_BRIGHTNESS 0x56 +#define ILI9341_WRITE_CA_MIN_BRIGHTNESS 0x5E +#define ILI9341_READ_CA_MIN_BRIGHTNESS 0x5F +#define ILI9341_READ_ID1 0xDA +#define ILI9341_READ_ID2 0xDB +#define ILI9341_READ_ID3 0xDC +#define ILI9341_RGB_INTERFACE_CONTROL 0xB0 +#define ILI9341_FRAME_RATE_CONTROL_1 0xB1 +#define ILI9341_FRAME_RATE_CONTROL_2 0xB2 +#define ILI9341_FRAME_RATE_CONTROL_3 0xB3 +#define ILI9341_DISPLAY_INVERSION_CONTROL 0xB4 +#define ILI9341_BLANKING_PORCH_CONTROL 0xB5 +#define ILI9341_DISPLAY_FUNCTION_CONTROL 0xB6 +#define ILI9341_ENTRY_MODE_SET 0xB7 +#define ILI9341_BACKLIGHT_CONTROL_1 0xB8 +#define ILI9341_BACKLIGHT_CONTROL_2 0xB9 +#define ILI9341_BACKLIGHT_CONTROL_3 0xBA +#define ILI9341_BACKLIGHT_CONTROL_4 0xBB +#define ILI9341_BACKLIGHT_CONTROL_5 0xBC +#define ILI9341_BACKLIGHT_CONTROL_7 0xBE +#define ILI9341_BACKLIGHT_CONTROL_8 0xBF +#define ILI9341_POWER_CONTROL_1 0xC0 +#define ILI9341_POWER_CONTROL_2 0xC1 +#define ILI9341_VCOM_CONTROL_1 0xC5 +#define ILI9341_VCOM_CONTROL_2 0xC7 +#define ILI9341_POWERA 0xCB +#define ILI9341_POWERB 0xCF +#define ILI9341_NV_MEMORY_WRITE 0xD0 +#define ILI9341_NV_PROTECTION_KEY 0xD1 +#define ILI9341_NV_STATUS_READ 0xD2 +#define ILI9341_READ_ID4 0xD3 +#define ILI9341_POSITIVE_GAMMA_CORRECTION 0xE0 +#define ILI9341_NEGATIVE_GAMMA_CORRECTION 0xE1 +#define ILI9341_DIGITAL_GAMMA_CONTROL_1 0xE2 +#define ILI9341_DIGITAL_GAMMA_CONTROL_2 0xE3 +#define ILI9341_DTCA 0xE8 +#define ILI9341_DTCB 0xEA +#define ILI9341_POWER_SEQ 0xED +#define ILI9341_3GAMMA_EN 0xF2 +#define ILI9341_INTERFACE_CONTROL 0xF6 +#define ILI9341_PUMP_RATIO_CONTROL 0xF7 // // ILI9341_MEMORY_ACCESS_CONTROL registers @@ -126,20 +126,20 @@ uint16_t background_color=DEFAULT_BG_COLOR; #define ILI9341_MADCTL_MH 0x04 #define ILI9341_MADCTL_RGB 0x00 -#define DISPLAY_ROTATION_270 (ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR) -#define DISPLAY_ROTATION_90 (ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR) -#define DISPLAY_ROTATION_0 (ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR) -#define DISPLAY_ROTATION_180 (ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR) +#define DISPLAY_ROTATION_270 (ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR) +#define DISPLAY_ROTATION_90 (ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR) +#define DISPLAY_ROTATION_0 (ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR) +#define DISPLAY_ROTATION_180 (ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR) // // Pin macros // -#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) +#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 ********************************** @@ -159,17 +159,17 @@ uint16_t background_color=DEFAULT_BG_COLOR; // 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_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_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) +#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 @@ -180,11 +180,11 @@ uint16_t background_color=DEFAULT_BG_COLOR; #ifdef __USE_DISPLAY_DMA__ static const stm32_dma_stream_t *dmatx = STM32_DMA_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM); -static uint32_t txdmamode = 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_DIR_M2P // Memory to Spi - | STM32_DMA_CR_DMEIE // - | STM32_DMA_CR_TEIE; +static uint32_t txdmamode = 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_DIR_M2P // Memory to Spi + | STM32_DMA_CR_DMEIE // + | STM32_DMA_CR_TEIE; static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { (void)spip; @@ -193,11 +193,11 @@ static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { 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) - | STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) - | STM32_DMA_CR_DIR_P2M - | STM32_DMA_CR_TCIE - | STM32_DMA_CR_DMEIE - | STM32_DMA_CR_TEIE; + | STM32_DMA_CR_PL(STM32_SPI_SPI1_DMA_PRIORITY) + | STM32_DMA_CR_DIR_P2M + | STM32_DMA_CR_TCIE + | STM32_DMA_CR_DMEIE + | STM32_DMA_CR_TEIE; static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { (void)spip; @@ -205,14 +205,14 @@ static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { } static void dmaStreamFlush(uint32_t len){ - while (len){ - // DMA data transfer limited by 65535 - uint16_t tx_size = len > 65535 ? 65535 : len; - dmaStreamSetTransactionSize(dmatx, tx_size); - dmaStreamEnable(dmatx); - len -= tx_size; - dmaWaitCompletion(dmatx); - } + while (len){ + // DMA data transfer limited by 65535 + uint16_t tx_size = len > 65535 ? 65535 : len; + dmaStreamSetTransactionSize(dmatx, tx_size); + dmaStreamEnable(dmatx); + len -= tx_size; + dmaWaitCompletion(dmatx); + } } #endif @@ -221,13 +221,13 @@ static void spi_init(void) rccEnableSPI1(FALSE); SPI1->CR1 = 0; SPI1->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_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 + | 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_BR_1; // Baud rate control SPI1->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; // + | SPI_CR2_FRXTH; // SPI_SR_RXNE generated every 8 bit data +// | SPI_CR2_SSOE; // #ifdef __USE_DISPLAY_DMA__ // Tx DMA init @@ -238,7 +238,7 @@ static void spi_init(void) dmaStreamSetPeripheral(dmarx, &SPI1->DR); // Enable DMA on SPI SPI1->CR2|= SPI_CR2_TXDMAEN // Tx DMA enable - | SPI_CR2_RXDMAEN; // Rx DMA enable + | SPI_CR2_RXDMAEN; // Rx DMA enable #endif SPI1->CR1|= SPI_CR1_SPE; //SPI enable } @@ -246,166 +246,166 @@ static void spi_init(void) // Disable inline for this function static void __attribute__ ((noinline)) send_command(uint8_t cmd, uint8_t len, const uint8_t *data) { - CS_LOW; - // while (SPI_TX_IS_NOT_EMPTY); - DC_CMD; - SPI_WRITE_8BIT(cmd); - // Need wait transfer complete and set data bit - while (SPI_IS_BUSY); - // Send command data (if need) - DC_DATA; - while (len-- > 0) { - while (SPI_TX_IS_NOT_EMPTY); - SPI_WRITE_8BIT(*data++); - } - //CS_HIGH; + CS_LOW; + //while (SPI_TX_IS_NOT_EMPTY); + DC_CMD; + SPI_WRITE_8BIT(cmd); + // Need wait transfer complete and set data bit + while (SPI_IS_BUSY); + // Send command data (if need) + DC_DATA; + while (len-- > 0) { + while (SPI_TX_IS_NOT_EMPTY); + SPI_WRITE_8BIT(*data++); + } + //CS_HIGH; } static const uint8_t ili9341_init_seq[] = { - // cmd, len, data..., - // SW reset - ILI9341_SOFTWARE_RESET, 0, - // display off - ILI9341_DISPLAY_OFF, 0, - // Power control B - ILI9341_POWERB, 3, 0x00, 0x83, 0x30, - // Power on sequence control - ILI9341_POWER_SEQ, 4, 0x64, 0x03, 0x12, 0x81, - //ILI9341_POWER_SEQ, 4, 0x55, 0x01, 0x23, 0x01, - // Driver timing control A - ILI9341_DTCA, 3, 0x85, 0x01, 0x79, - //ILI9341_DTCA, 3, 0x84, 0x11, 0x7a, - // Power control A - ILI9341_POWERA, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, - // Pump ratio control - ILI9341_PUMP_RATIO_CONTROL, 1, 0x20, - // Driver timing control B - ILI9341_DTCB, 2, 0x00, 0x00, - // POWER_CONTROL_1 - ILI9341_POWER_CONTROL_1, 1, 0x26, - // POWER_CONTROL_2 - ILI9341_POWER_CONTROL_2, 1, 0x11, - // VCOM_CONTROL_1 - ILI9341_VCOM_CONTROL_1, 2, 0x35, 0x3E, - // VCOM_CONTROL_2 - ILI9341_VCOM_CONTROL_2, 1, 0xBE, - // MEMORY_ACCESS_CONTROL - //ILI9341_MEMORY_ACCESS_CONTROL, 1, 0x48, // portlait - ILI9341_MEMORY_ACCESS_CONTROL, 1, DISPLAY_ROTATION_0, // landscape - // COLMOD_PIXEL_FORMAT_SET : 16 bit pixel - ILI9341_PIXEL_FORMAT_SET, 1, 0x55, - // Frame Rate - ILI9341_FRAME_RATE_CONTROL_1, 2, 0x00, 0x1B, - // Gamma Function Disable - ILI9341_3GAMMA_EN, 1, 0x08, - // gamma set for curve 01/2/04/08 - ILI9341_GAMMA_SET, 1, 0x01, - // positive gamma correction -// ILI9341_POSITIVE_GAMMA_CORRECTION, 15, 0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0x87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00, - // negativ gamma correction -// ILI9341_NEGATIVE_GAMMA_CORRECTION, 15, 0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F, - // Column Address Set -// ILI9341_COLUMN_ADDRESS_SET, 4, 0x00, 0x00, 0x01, 0x3f, // width 320 - // Page Address Set -// ILI9341_PAGE_ADDRESS_SET, 4, 0x00, 0x00, 0x00, 0xef, // height 240 - // entry mode - ILI9341_ENTRY_MODE_SET, 1, 0x06, - // display function control - ILI9341_DISPLAY_FUNCTION_CONTROL, 4, 0x0A, 0x82, 0x27, 0x00, - // Interface Control (set WEMODE=0) - ILI9341_INTERFACE_CONTROL, 3, 0x00, 0x00, 0x00, - // control display - //ILI9341_WRITE_CTRL_DISPLAY, 1, 0x0c, - // diaplay brightness - //ILI9341_WRITE_BRIGHTNESS, 1, 0xff, - // sleep out - ILI9341_SLEEP_OUT, 0, - // display on - ILI9341_DISPLAY_ON, 0, - 0 // sentinel + // cmd, len, data..., + // SW reset + ILI9341_SOFTWARE_RESET, 0, + // display off + ILI9341_DISPLAY_OFF, 0, + // Power control B + ILI9341_POWERB, 3, 0x00, 0x83, 0x30, + // Power on sequence control + ILI9341_POWER_SEQ, 4, 0x64, 0x03, 0x12, 0x81, + //ILI9341_POWER_SEQ, 4, 0x55, 0x01, 0x23, 0x01, + // Driver timing control A + ILI9341_DTCA, 3, 0x85, 0x01, 0x79, + //ILI9341_DTCA, 3, 0x84, 0x11, 0x7a, + // Power control A + ILI9341_POWERA, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, + // Pump ratio control + ILI9341_PUMP_RATIO_CONTROL, 1, 0x20, + // Driver timing control B + ILI9341_DTCB, 2, 0x00, 0x00, + // POWER_CONTROL_1 + ILI9341_POWER_CONTROL_1, 1, 0x26, + // POWER_CONTROL_2 + ILI9341_POWER_CONTROL_2, 1, 0x11, + // VCOM_CONTROL_1 + ILI9341_VCOM_CONTROL_1, 2, 0x35, 0x3E, + // VCOM_CONTROL_2 + ILI9341_VCOM_CONTROL_2, 1, 0xBE, + // MEMORY_ACCESS_CONTROL + //ILI9341_MEMORY_ACCESS_CONTROL, 1, 0x48, // portlait + ILI9341_MEMORY_ACCESS_CONTROL, 1, DISPLAY_ROTATION_0, // landscape + // COLMOD_PIXEL_FORMAT_SET : 16 bit pixel + ILI9341_PIXEL_FORMAT_SET, 1, 0x55, + // Frame Rate + ILI9341_FRAME_RATE_CONTROL_1, 2, 0x00, 0x1B, + // Gamma Function Disable + ILI9341_3GAMMA_EN, 1, 0x08, + // gamma set for curve 01/2/04/08 + ILI9341_GAMMA_SET, 1, 0x01, + // positive gamma correction +//ILI9341_POSITIVE_GAMMA_CORRECTION, 15, 0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0x87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00, + // negativ gamma correction +//ILI9341_NEGATIVE_GAMMA_CORRECTION, 15, 0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F, + // Column Address Set +//ILI9341_COLUMN_ADDRESS_SET, 4, 0x00, 0x00, 0x01, 0x3f, // width 320 + // Page Address Set +//ILI9341_PAGE_ADDRESS_SET, 4, 0x00, 0x00, 0x00, 0xef, // height 240 + // entry mode + ILI9341_ENTRY_MODE_SET, 1, 0x06, + // display function control + ILI9341_DISPLAY_FUNCTION_CONTROL, 4, 0x0A, 0x82, 0x27, 0x00, + // Interface Control (set WEMODE=0) + ILI9341_INTERFACE_CONTROL, 3, 0x00, 0x00, 0x00, + // control display + //ILI9341_WRITE_CTRL_DISPLAY, 1, 0x0c, + // diaplay brightness + //ILI9341_WRITE_BRIGHTNESS, 1, 0xff, + // sleep out + ILI9341_SLEEP_OUT, 0, + // display on + ILI9341_DISPLAY_ON, 0, + 0 // sentinel }; void ili9341_init(void) { - spi_init(); - DC_DATA; - RESET_ASSERT; - chThdSleepMilliseconds(10); - RESET_NEGATE; - const uint8_t *p; - for (p = ili9341_init_seq; *p; ) { - send_command(p[0], p[1], &p[2]); - p += 2 + p[1]; - chThdSleepMilliseconds(5); - } + spi_init(); + DC_DATA; + RESET_ASSERT; + chThdSleepMilliseconds(10); + RESET_NEGATE; + const uint8_t *p; + for (p = ili9341_init_seq; *p; ) { + send_command(p[0], p[1], &p[2]); + p += 2 + p[1]; + chThdSleepMilliseconds(5); + } } #ifndef __USE_DISPLAY_DMA__ void ili9341_fill(int x, int y, int w, int h, int 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 yy = __REV16(y|((y+h-1)<<16)); - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); - send_command(ILI9341_MEMORY_WRITE, 0, NULL); - int32_t len = w * h; - while (len-- > 0){ - while (SPI_TX_IS_NOT_EMPTY); - SPI_WRITE_16BIT(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 yy = __REV16(y|((y+h-1)<<16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); + send_command(ILI9341_MEMORY_WRITE, 0, NULL); + int32_t len = w * h; + while (len-- > 0){ + while (SPI_TX_IS_NOT_EMPTY); + SPI_WRITE_16BIT(color); + } } 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 yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) }; - uint16_t *buf = spi_buffer; - uint32_t xx = __REV16(x|((x+w-1)<<16)); - uint32_t yy = __REV16(y|((y+h-1)<<16)); - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); - send_command(ILI9341_MEMORY_WRITE, 0, NULL); - int32_t len = w * h; - while (len-- > 0){ - while (SPI_TX_IS_NOT_EMPTY); - SPI_WRITE_16BIT(*buf++); - } +//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) }; + uint16_t *buf = spi_buffer; + uint32_t xx = __REV16(x|((x+w-1)<<16)); + uint32_t yy = __REV16(y|((y+h-1)<<16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); + send_command(ILI9341_MEMORY_WRITE, 0, NULL); + int32_t len = w * h; + while (len-- > 0){ + while (SPI_TX_IS_NOT_EMPTY); + SPI_WRITE_16BIT(*buf++); + } } 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; + // 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) { -// 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 yy = __REV16(y|((y+h-1)<<16)); - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); - send_command(ILI9341_MEMORY_READ, 0, NULL); - - // Skip data from rx buffer - while (SPI_RX_IS_NOT_EMPTY) - (void) SPI_READ_DATA; - // require 8bit dummy clock - ssp_sendrecvdata(); - while (len-- > 0) { - // read data is always 18bit - uint8_t r = ssp_sendrecvdata(); - uint8_t g = ssp_sendrecvdata(); - uint8_t b = ssp_sendrecvdata(); - *out++ = RGB565(r,g,b); - } - CS_HIGH; +//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 yy = __REV16(y|((y+h-1)<<16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); + send_command(ILI9341_MEMORY_READ, 0, NULL); + + // Skip data from rx buffer + while (SPI_RX_IS_NOT_EMPTY) + (void) SPI_READ_DATA; + // require 8bit dummy clock + ssp_sendrecvdata(); + while (len-- > 0) { + // read data is always 18bit + uint8_t r = ssp_sendrecvdata(); + uint8_t g = ssp_sendrecvdata(); + uint8_t b = ssp_sendrecvdata(); + *out++ = RGB565(r,g,b); + } + CS_HIGH; } #else // @@ -415,162 +415,179 @@ void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out) // Fill region by some color void ili9341_fill(int x, int y, int w, int h, int color) { - uint32_t xx = __REV16(x|((x+w-1)<<16)); - uint32_t yy = __REV16(y|((y+h-1)<<16)); - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); - send_command(ILI9341_MEMORY_WRITE, 0, NULL); - - dmaStreamSetMemory0(dmatx, &color); - dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD); - dmaStreamFlush(w * h); + uint32_t xx = __REV16(x|((x+w-1)<<16)); + uint32_t yy = __REV16(y|((y+h-1)<<16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); + send_command(ILI9341_MEMORY_WRITE, 0, NULL); + + dmaStreamSetMemory0(dmatx, &color); + dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD); + dmaStreamFlush(w * h); +} + +void ili9341_bulk_8bit(int x, int y, int w, int h, uint16_t *palette){ + uint32_t xx = __REV16(x|((x+w-1)<<16)); + uint32_t yy = __REV16(y|((y+h-1)<<16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); + send_command(ILI9341_MEMORY_WRITE, 0, NULL); + + uint8_t *buf = (uint8_t *)spi_buffer; + int32_t len = w * h; + while (len-- > 0){ + uint16_t color = palette[*buf++]; + while (SPI_TX_IS_NOT_EMPTY); + SPI_WRITE_16BIT(color); + } } + // Copy spi_buffer to region void ili9341_bulk(int x, int y, int w, int h) { - uint32_t xx = __REV16(x|((x+w-1)<<16)); - uint32_t yy = __REV16(y|((y+h-1)<<16)); - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); - send_command(ILI9341_MEMORY_WRITE, 0, NULL); - - // Init Tx DMA mem->spi, set size, mode (spi and mem data size is 16 bit) - dmaStreamSetMemory0(dmatx, spi_buffer); - dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_MINC); - dmaStreamFlush(w * h); + uint32_t xx = __REV16(x|((x+w-1)<<16)); + uint32_t yy = __REV16(y|((y+h-1)<<16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); + send_command(ILI9341_MEMORY_WRITE, 0, NULL); + + // Init Tx DMA mem->spi, set size, mode (spi and mem data size is 16 bit) + dmaStreamSetMemory0(dmatx, spi_buffer); + dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_MINC); + dmaStreamFlush(w * h); } // Copy screen data to buffer // 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) { - uint8_t dummy_tx = 0; - uint8_t *rgbbuf=(uint8_t *)out; - uint16_t data_size = len * 3 + 1; - uint32_t xx = __REV16(x|((x+w-1)<<16)); - uint32_t yy = __REV16(y|((y+h-1)<<16)); - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); - 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) - dmaStreamSetMemory0(dmarx, rgbbuf); - dmaStreamSetTransactionSize(dmarx, data_size); - 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, data_size); - dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE); - - // Start DMA exchange - dmaStreamEnable(dmatx); - dmaStreamEnable(dmarx); - // Wait DMA completion - dmaWaitCompletion(dmatx); - dmaWaitCompletion(dmarx); - CS_HIGH; - - // Parce recived data - // Skip dummy 8-bit read - rgbbuf++; - while (len-- > 0) { - uint8_t r, g, b; - // read data is always 18bit - r = rgbbuf[0]; - g = rgbbuf[1]; - b = rgbbuf[2]; - *out++ = RGB565(r,g,b); - rgbbuf+=3; - } + uint8_t dummy_tx = 0; + uint8_t *rgbbuf=(uint8_t *)out; + uint16_t data_size = len * 3 + 1; + uint32_t xx = __REV16(x|((x+w-1)<<16)); + uint32_t yy = __REV16(y|((y+h-1)<<16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); + 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) + dmaStreamSetMemory0(dmarx, rgbbuf); + dmaStreamSetTransactionSize(dmarx, data_size); + 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, data_size); + dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE); + + // Start DMA exchange + dmaStreamEnable(dmatx); + dmaStreamEnable(dmarx); + // Wait DMA completion + dmaWaitCompletion(dmatx); + dmaWaitCompletion(dmarx); + CS_HIGH; + + // Parce recived data + // Skip dummy 8-bit read + rgbbuf++; + while (len-- > 0) { + uint8_t r, g, b; + // read data is always 18bit + r = rgbbuf[0]; + g = rgbbuf[1]; + b = rgbbuf[2]; + *out++ = RGB565(r,g,b); + rgbbuf+=3; + } } #endif void clearScreen(void){ - ili9341_fill(0, 0, ILI9341_WIDTH, ILI9341_HEIGHT, background_color); + ili9341_fill(0, 0, ILI9341_WIDTH, ILI9341_HEIGHT, background_color); } void setForegroundColor(uint16_t fg) {foreground_color = fg;} void setBackgroundColor(uint16_t bg) {background_color = bg;} void ili9341_setRotation(uint8_t r) { -// static const uint8_t rotation_const[]={DISPLAY_ROTATION_0, DISPLAY_ROTATION_90, DISPLAY_ROTATION_180, DISPLAY_ROTATION_270}; - send_command(ILI9341_MEMORY_ACCESS_CONTROL, 1, &r); +// static const uint8_t rotation_const[]={DISPLAY_ROTATION_0, DISPLAY_ROTATION_90, DISPLAY_ROTATION_180, DISPLAY_ROTATION_270}; + send_command(ILI9341_MEMORY_ACCESS_CONTROL, 1, &r); } void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *bitmap){ - uint16_t *buf = spi_buffer; - for(uint16_t c = 0; c < height; c++) { - uint8_t bits = *bitmap++; - for (uint16_t r = 0; r < width; r++) { - *buf++ = (0x80 & bits) ? foreground_color : background_color; - bits <<= 1; - } - } - ili9341_bulk(x, y, width, height); + uint16_t *buf = spi_buffer; + for(uint16_t c = 0; c < height; c++) { + uint8_t bits = *bitmap++; + for (uint16_t r = 0; r < width; r++) { + *buf++ = (0x80 & bits) ? foreground_color : background_color; + bits <<= 1; + } + } + ili9341_bulk(x, y, width, height); } void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *bitmap){ - uint16_t *buf = spi_buffer; - for(uint16_t c = 0; c < height; c++) { - uint16_t bits = *bitmap++; - for (uint16_t r = 0; r < width; r++) { - *buf++ = (0x8000 & bits) ? foreground_color : background_color; - bits <<= 1; - } + uint16_t *buf = spi_buffer; + for(uint16_t c = 0; c < height; c++) { + uint16_t bits = *bitmap++; + for (uint16_t r = 0; r < width; r++) { + *buf++ = (0x8000 & bits) ? foreground_color : background_color; + bits <<= 1; } - ili9341_bulk(x, y, width, height); + } + ili9341_bulk(x, y, width, height); } 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)); } void ili9341_drawstring(const char *str, int x, int y) { - while (*str) { - uint8_t ch = *str++; - const uint8_t *char_buf = FONT_GET_DATA(ch); - uint16_t w = FONT_GET_WIDTH(ch); - blit8BitWidthBitmap(x, y, w, FONT_GET_HEIGHT, char_buf); - x+=w; - } + while (*str) { + uint8_t ch = *str++; + const uint8_t *char_buf = FONT_GET_DATA(ch); + uint16_t w = FONT_GET_WIDTH(ch); + blit8BitWidthBitmap(x, y, w, FONT_GET_HEIGHT, char_buf); + x+=w; + } } void ili9341_drawstringV(const char *str, int x, int y){ - ili9341_setRotation(DISPLAY_ROTATION_270); - ili9341_drawstring(str, ILI9341_HEIGHT-y, x); - ili9341_setRotation(DISPLAY_ROTATION_0); + ili9341_setRotation(DISPLAY_ROTATION_270); + ili9341_drawstring(str, ILI9341_HEIGHT-y, x); + ili9341_setRotation(DISPLAY_ROTATION_0); } int ili9341_drawchar_size(uint8_t ch, int x, int y, uint8_t size) { - uint16_t *buf = spi_buffer; - const uint8_t *char_buf = FONT_GET_DATA(ch); - uint16_t w=FONT_GET_WIDTH(ch); - for(int c = 0; c < FONT_GET_HEIGHT; c++, char_buf++){ - for (int i=0;i x1) { - SWAP(x0, x1); - SWAP(y0, y1); - } + if (x0 > x1) { + SWAP(x0, x1); + SWAP(y0, y1); + } - while (x0 <= x1) { - int dx = x1 - x0 + 1; - int dy = y1 - y0; - if (dy >= 0) { - dy++; - if (dy > dx) { - dy /= dx; dx = 1; - } else { - dx /= dy; dy = 1; - } - } else { - dy--; - if (-dy > dx) { - dy /= dx; dx = 1; - } else { - dx /= -dy;dy = -1; - } - } - if (dy > 0) - ili9341_fill(x0, y0, dx, dy, foreground_color); - else - ili9341_fill(x0, y0+dy, dx, -dy, foreground_color); - x0 += dx; - y0 += dy; + while (x0 <= x1) { + int dx = x1 - x0 + 1; + int dy = y1 - y0; + if (dy >= 0) { + dy++; + if (dy > dx) { + dy /= dx; dx = 1; + } else { + dx /= dy; dy = 1; + } + } else { + dy--; + if (-dy > dx) { + dy /= dx; dx = 1; + } else { + dx /= -dy;dy = -1; + } } + if (dy > 0) + ili9341_fill(x0, y0, dx, dy, foreground_color); + else + ili9341_fill(x0, y0+dy, dx, -dy, foreground_color); + x0 += dx; + y0 += dy; + } } #if 0 static const uint16_t colormap[] = { - RGBHEX(0x00ff00), RGBHEX(0x0000ff), RGBHEX(0xff0000), - RGBHEX(0x00ffff), RGBHEX(0xff00ff), RGBHEX(0xffff00) + RGBHEX(0x00ff00), RGBHEX(0x0000ff), RGBHEX(0xff0000), + RGBHEX(0x00ffff), RGBHEX(0xff00ff), RGBHEX(0xffff00) }; void ili9341_test(int mode) { - int x, y; - int i; - switch (mode) { - default: + int x, y; + int i; + switch (mode) { + default: #if 1 - ili9341_fill(0, 0, 320, 240, 0); - for (y = 0; y < 240; y++) { - ili9341_fill(0, y, 320, 1, RGB(240-y, y, (y + 120) % 256)); - } - break; - case 1: - ili9341_fill(0, 0, 320, 240, 0); - for (y = 0; y < 240; y++) { - for (x = 0; x < 320; x++) { - ili9341_pixel(x, y, (y<<8)|x); - } - } - break; - case 2: - //send_command16(0x55, 0xff00); - ili9341_pixel(64, 64, 0xaa55); - break; + ili9341_fill(0, 0, 320, 240, 0); + for (y = 0; y < 240; y++) { + ili9341_fill(0, y, 320, 1, RGB(240-y, y, (y + 120) % 256)); + } + break; + case 1: + ili9341_fill(0, 0, 320, 240, 0); + for (y = 0; y < 240; y++) { + for (x = 0; x < 320; x++) { + ili9341_pixel(x, y, (y<<8)|x); + } + } + break; + case 2: + //send_command16(0x55, 0xff00); + ili9341_pixel(64, 64, 0xaa55); + break; #endif #if 1 - case 3: - for (i = 0; i < 10; i++) - ili9341_drawfont(i, i*20, 120); - break; + case 3: + for (i = 0; i < 10; i++) + ili9341_drawfont(i, i*20, 120); + break; #endif #if 0 - case 4: - draw_grid(10, 8, 29, 29, 15, 0, 0xffff, 0); - break; + case 4: + draw_grid(10, 8, 29, 29, 15, 0, 0xffff, 0); + break; #endif - case 4: - ili9341_line(0, 0, 15, 100); - ili9341_line(0, 0, 100, 100); - ili9341_line(0, 15, 100, 0); - ili9341_line(0, 100, 100, 0); - break; - } + case 4: + ili9341_line(0, 0, 15, 100); + ili9341_line(0, 0, 100, 100); + ili9341_line(0, 15, 100, 0); + ili9341_line(0, 100, 100, 0); + break; + } } #endif diff --git a/main.c b/main.c index c6c5a961..69245fd1 100644 --- a/main.c +++ b/main.c @@ -51,34 +51,38 @@ static BaseSequentialStream *shell_stream = (BaseSequentialStream *)&SDU1; typedef void (*vna_shellcmd_t)(int argc, char *argv[]); #define VNA_SHELL_FUNCTION(command_name) static void command_name(int argc, char *argv[]) -// Shell command line buffer +// Shell command line buffer, args, nargs, and function ptr static char shell_line[VNA_SHELL_MAX_LENGTH]; +static char *shell_args[VNA_SHELL_MAX_ARGUMENTS + 1]; +static uint16_t shell_nargs; +static volatile vna_shellcmd_t shell_function = 0; //#define ENABLED_DUMP +// Allow get threads debug info //#define ENABLE_THREADS_COMMAND +// RTC time not used //#define ENABLE_TIME_COMMAND +// Enable vbat_offset command, allow change battery voltage correction in config #define ENABLE_VBAT_OFFSET_COMMAND +// Info about NanoVNA, need fore soft #define ENABLE_INFO_COMMAND +// Enable color command, allow change config color for traces, grid, menu +#define ENABLE_COLOR_COMMAND static void apply_error_term_at(int i); static void apply_edelay_at(int i); static void cal_interpolate(int s); -void update_frequencies(void); -void set_frequencies(uint32_t start, uint32_t stop, uint16_t points); - +static void update_frequencies(void); +static void set_frequencies(uint32_t start, uint32_t stop, uint16_t points); static bool sweep(bool break_on_operation); static void transform_domain(void); -static MUTEX_DECL(mutex); - #define DRIVE_STRENGTH_AUTO (-1) #define FREQ_HARMONICS (config.harmonic_freq_threshold) #define IS_HARMONIC_MODE(f) ((f) > FREQ_HARMONICS) // Obsolete, always use interpolate #define cal_auto_interpolate TRUE -static int32_t frequency_offset = 5000; -static uint32_t frequency = 10000000; static int8_t drive_strength = DRIVE_STRENGTH_AUTO; int8_t sweep_mode = SWEEP_ENABLE; volatile uint8_t redraw_request = 0; // contains REDRAW_XXX flags @@ -107,37 +111,38 @@ static THD_FUNCTION(Thread1, arg) while (1) { bool completed = false; if (sweep_mode&(SWEEP_ENABLE|SWEEP_ONCE)) { - chMtxLock(&mutex); completed = sweep(true); sweep_mode&=~SWEEP_ONCE; - chMtxUnlock(&mutex); } else { __WFI(); } - - chMtxLock(&mutex); + // Run Shell command in sweep thread + if (shell_function){ + shell_function(shell_nargs-1, &shell_args[1]); + shell_function = 0; + osalThreadSleepMilliseconds(10); + continue; + } + // Process UI inputs ui_process(); - - if (sweep_mode&SWEEP_ENABLE) { - // calculate trace coordinates and plot only if scan completed - if (completed) { - if ((domain_mode & DOMAIN_MODE) == DOMAIN_TIME) - transform_domain(); - plot_into_index(measured); - redraw_request |= REDRAW_CELLS|REDRAW_BATTERY; - - if (uistat.marker_tracking) { - int i = marker_search(); - if (i != -1 && active_marker != -1) { - markers[active_marker].index = i; - redraw_request |= REDRAW_MARKER; - } + // Process collected data, calculate trace coordinates and plot only if scan completed + if (sweep_mode&SWEEP_ENABLE && completed) { + if ((domain_mode & DOMAIN_MODE) == DOMAIN_TIME) + transform_domain(); + // Prepare draw graphics, cache all lines, mark screen cells for redraw + plot_into_index(measured); + redraw_request |= REDRAW_CELLS|REDRAW_BATTERY; + + if (uistat.marker_tracking) { + int i = marker_search(); + if (i != -1 && active_marker != -1) { + markers[active_marker].index = i; + redraw_request |= REDRAW_MARKER; } } } // plot trace and other indications as raster draw_all(completed); // flush markmap only if scan completed to prevent remaining traces - chMtxUnlock(&mutex); } } @@ -325,7 +330,7 @@ static int adjust_gain(uint32_t newfreq) { int new_order = newfreq / FREQ_HARMONICS; - int old_order = frequency / FREQ_HARMONICS; + int old_order = si5351_getFrequency() / FREQ_HARMONICS; if (new_order != old_order) { tlv320aic3204_set_gain(gain_table[new_order], gain_table[new_order]); return DELAY_GAIN_CHANGE; @@ -340,9 +345,7 @@ int set_frequency(uint32_t freq) if (ds == DRIVE_STRENGTH_AUTO) { ds = freq > FREQ_HARMONICS ? SI5351_CLK_DRIVE_STRENGTH_8MA : SI5351_CLK_DRIVE_STRENGTH_2MA; } - delay += si5351_set_frequency_with_offset(freq, frequency_offset, ds); - - frequency = freq; + delay += si5351_set_frequency_with_offset(freq, ds); return delay; } @@ -364,13 +367,30 @@ static int32_t my_atoi(const char *p){ } // Convert string to uint32 -uint32_t my_atoui(const char *p){ - uint32_t value = 0; - uint32_t c; +// 0x - for hex radix +// 0o - for oct radix +// 0b - for bin radix +// default dec radix +uint32_t my_atoui(const char *p) { + uint32_t value = 0, radix = 10, c; if (*p == '+') p++; - while ((c = *p++ - '0') < 10) - value = value * 10 + c; - return value; + if (*p == '0') { + switch (p[1]) { + case 'x': radix = 16; break; + case 'o': radix = 8; break; + case 'b': radix = 2; break; + default: goto calculate; + } + p+=2; + } +calculate: + while (1) { + c = *p++ - '0'; + // c = to_upper(*p) - 'A' + 10 + if (c >= 'A' - '0') c = (c&(~0x20)) - ('A' - '0') + 10; + if (c >= radix) return value; + value = value * radix + c; + } } double @@ -442,36 +462,35 @@ static int getStringIndex(char *v, const char *list){ VNA_SHELL_FUNCTION(cmd_offset) { - if (argc != 1) { - shell_printf("usage: offset {frequency offset(Hz)}\r\n"); - return; - } - frequency_offset = my_atoui(argv[0]); - set_frequency(frequency); + if (argc != 1) { + shell_printf("usage: offset {frequency offset(Hz)}\r\n"); + return; + } + si5351_set_frequency_offset(my_atoi(argv[0])); } VNA_SHELL_FUNCTION(cmd_freq) { - if (argc != 1) { - goto usage; - } - uint32_t freq = my_atoui(argv[0]); + if (argc != 1) { + goto usage; + } + uint32_t freq = my_atoui(argv[0]); - pause_sweep(); - set_frequency(freq); - return; + pause_sweep(); + set_frequency(freq); + return; usage: - shell_printf("usage: freq {frequency(Hz)}\r\n"); + shell_printf("usage: freq {frequency(Hz)}\r\n"); } VNA_SHELL_FUNCTION(cmd_power) { if (argc != 1) { - shell_printf("usage: power {0-3|-1}\r\n"); - return; + shell_printf("usage: power {0-3|-1}\r\n"); + return; } drive_strength = my_atoi(argv[0]); - set_frequency(frequency); +// set_frequency(frequency); } #ifdef ENABLE_TIME_COMMAND @@ -496,7 +515,7 @@ VNA_SHELL_FUNCTION(cmd_dac) "current value: %d\r\n", config.dac_value); return; } - value = my_atoi(argv[0]); + value = my_atoui(argv[0]); config.dac_value = value; dacPutChannelX(&DACD2, 0, value); } @@ -718,6 +737,7 @@ config_t config = { .trace_color = { DEFAULT_TRACE_1_COLOR, DEFAULT_TRACE_2_COLOR, DEFAULT_TRACE_3_COLOR, DEFAULT_TRACE_4_COLOR }, // .touch_cal = { 693, 605, 124, 171 }, // 2.4 inch LCD panel .touch_cal = { 338, 522, 153, 192 }, // 2.8 inch LCD panel + .freq_mode = FREQ_MODE_START_STOP, .harmonic_freq_threshold = 300000000, .vbat_offset = 500 }; @@ -783,13 +803,12 @@ bool sweep(bool break_on_operation) int i, delay; // blink LED while scanning palClearPad(GPIOC, GPIOC_LED); - // Power stabilization after LED off, also align timings - // Also touch made some - DSP_START(1); DSP_WAIT_READY; + // Power stabilization after LED off, also align timings on i == 0 for (i = 0; i < sweep_points; i++) { // 5300 + if (frequencies[i] == 0) break; delay = set_frequency(frequencies[i]); // 700 - tlv320aic3204_select(0); // 60 CH0:REFLECT - DSP_START(delay); // 1900 + tlv320aic3204_select(0); // 60 CH0:REFLECT, reset and begin measure + DSP_START(delay+((i==0)?1:0)); // 1900 //================================================ // Place some code thats need execute while delay //================================================ @@ -797,7 +816,7 @@ bool sweep(bool break_on_operation) // calculate reflection coefficient (*sample_func)(measured[0][i]); // 60 - tlv320aic3204_select(1); // 60 CH1:TRANSMISSION + tlv320aic3204_select(1); // 60 CH1:TRANSMISSION, reset and begin measure DSP_START(DELAY_CHANNEL_CHANGE); // 1700 //================================================ // Place some code thats need execute while delay @@ -825,9 +844,9 @@ VNA_SHELL_FUNCTION(cmd_scan) { uint32_t start, stop; int16_t points = sweep_points; - - if (argc != 2 && argc != 3) { - shell_printf("usage: scan {start(Hz)} {stop(Hz)} [points]\r\n"); + int i; + if (argc < 2 || argc > 4) { + shell_printf("usage: scan {start(Hz)} {stop(Hz)} [points] [outmask]\r\n"); return; } @@ -837,26 +856,33 @@ VNA_SHELL_FUNCTION(cmd_scan) shell_printf("frequency range is invalid\r\n"); return; } - if (argc == 3) { + if (argc >= 3) { points = my_atoi(argv[2]); - if (points <= 0 || points > sweep_points) { - shell_printf("sweep points exceeds range\r\n"); + if (points <= 0 || points > POINTS_COUNT) { + shell_printf("sweep points exceeds range "define_to_STR(POINTS_COUNT)"\r\n"); return; } } - pause_sweep(); - chMtxLock(&mutex); set_frequencies(start, stop, points); if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY)) cal_interpolate(lastsaveid); - - sweep_mode|= SWEEP_ONCE; - chMtxUnlock(&mutex); - - // wait finishing sweep - while (sweep_mode&SWEEP_ONCE) - chThdSleepMilliseconds(10); + pause_sweep(); + sweep(false); + // Output data after if set (faster data recive) + if (argc == 4){ + uint16_t mask = my_atoui(argv[3]); + if (mask) + for (i = 0; i < points; i++){ + if (mask&1) + shell_printf("%u ", frequencies[i]); + if (mask&2) + shell_printf("%f %f ", measured[0][i][0], measured[0][i][1]); + if (mask&4) + shell_printf("%f %f ", measured[1][i][0], measured[1][i][1]); + shell_printf("\r\n"); + } + } } static void @@ -887,7 +913,7 @@ update_marker_index(void) } } -void +static void set_frequencies(uint32_t start, uint32_t stop, uint16_t points) { uint32_t i; @@ -905,21 +931,16 @@ set_frequencies(uint32_t start, uint32_t stop, uint16_t points) } } // disable at out of sweep range - for (; i < sweep_points; i++) + for (; i < POINTS_COUNT; i++) frequencies[i] = 0; } -void +static void update_frequencies(void) { uint32_t start, stop; - if (frequency0 < frequency1) { - start = frequency0; - stop = frequency1; - } else { - start = frequency1; - stop = frequency0; - } + start = get_sweep_frequency(ST_START); + stop = get_sweep_frequency(ST_STOP); set_frequencies(start, stop, sweep_points); // operation_requested|= OP_FREQCHANGE; @@ -930,28 +951,6 @@ update_frequencies(void) update_grid(); } -static void -freq_mode_startstop(void) -{ - if (frequency0 > frequency1) { - ensure_edit_config(); - uint32_t f = frequency1; - frequency1 = frequency0; - frequency0 = f; - } -} - -static void -freq_mode_centerspan(void) -{ - if (frequency0 <= frequency1) { - ensure_edit_config(); - uint32_t f = frequency1; - frequency1 = frequency0; - frequency0 = f; - } -} - void set_sweep_frequency(int type, uint32_t freq) { @@ -963,11 +962,11 @@ set_sweep_frequency(int type, uint32_t freq) if (freq > STOP_MAX) freq = STOP_MAX; + ensure_edit_config(); switch (type) { case ST_START: - freq_mode_startstop(); + config.freq_mode&=~FREQ_MODE_CENTER_SPAN; if (frequency0 != freq) { - ensure_edit_config(); frequency0 = freq; // if start > stop then make start = stop if (frequency1 < freq) @@ -975,9 +974,8 @@ set_sweep_frequency(int type, uint32_t freq) } break; case ST_STOP: - freq_mode_startstop(); + config.freq_mode&=~FREQ_MODE_CENTER_SPAN; if (frequency1 != freq) { - ensure_edit_config(); frequency1 = freq; // if start > stop then make start = stop if (frequency0 > freq) @@ -985,25 +983,23 @@ set_sweep_frequency(int type, uint32_t freq) } break; case ST_CENTER: - freq_mode_centerspan(); - uint32_t center = FREQ_CENTER(); + config.freq_mode|=FREQ_MODE_CENTER_SPAN; + uint32_t center = frequency0/2 + frequency1/2; if (center != freq) { - uint32_t span = FREQ_SPAN(); - ensure_edit_config(); + uint32_t span = frequency1 - frequency0; if (freq < START_MIN + span/2) { span = (freq - START_MIN) * 2; } if (freq > STOP_MAX - span/2) { span = (STOP_MAX - freq) * 2; } - frequency0 = freq + span/2; - frequency1 = freq - span/2; + frequency0 = freq - span/2; + frequency1 = freq + span/2; } break; case ST_SPAN: - freq_mode_centerspan(); - if (frequency0 - frequency1 != freq) { - ensure_edit_config(); + config.freq_mode|=FREQ_MODE_CENTER_SPAN; + if (frequency1 - frequency0 != freq) { uint32_t center = frequency0/2 + frequency1/2; if (center < START_MIN + freq/2) { center = START_MIN + freq/2; @@ -1011,14 +1007,13 @@ set_sweep_frequency(int type, uint32_t freq) if (center > STOP_MAX - freq/2) { center = STOP_MAX - freq/2; } - frequency1 = center - freq/2; - frequency0 = center + freq/2; + frequency0 = center - freq/2; + frequency1 = center + freq/2; } break; case ST_CW: - freq_mode_centerspan(); + config.freq_mode|=FREQ_MODE_CENTER_SPAN; if (frequency0 != freq || frequency1 != freq) { - ensure_edit_config(); frequency0 = freq; frequency1 = freq; } @@ -1032,22 +1027,14 @@ set_sweep_frequency(int type, uint32_t freq) uint32_t get_sweep_frequency(int type) { - if (frequency0 <= frequency1) { - switch (type) { - case ST_START: return frequency0; - case ST_STOP: return frequency1; - case ST_CENTER: return frequency0/2 + frequency1/2; - case ST_SPAN: return frequency1 - frequency0; - case ST_CW: return frequency0/2 + frequency1/2; - } - } else { - switch (type) { - case ST_START: return frequency1; - case ST_STOP: return frequency0; + // Obsolete, ensure correct start/stop, start always must be < stop + if (frequency0>frequency1) {uint32_t t=frequency0; frequency0=frequency1; frequency1=t;} + switch (type) { + case ST_START: return frequency0; + case ST_STOP: return frequency1; case ST_CENTER: return frequency0/2 + frequency1/2; - case ST_SPAN: return frequency0 - frequency1; - case ST_CW: return frequency0/2 + frequency1/2; - } + case ST_SPAN: return frequency1 - frequency0; + case ST_CW: return frequency0; } return 0; } @@ -1055,7 +1042,7 @@ get_sweep_frequency(int type) VNA_SHELL_FUNCTION(cmd_sweep) { if (argc == 0) { - shell_printf("%d %d %d\r\n", frequency0, frequency1, sweep_points); + shell_printf("%d %d %d\r\n", get_sweep_frequency(ST_START), get_sweep_frequency(ST_STOP), sweep_points); return; } else if (argc > 3) { goto usage; @@ -1125,7 +1112,7 @@ adjust_ed(void) // prepare 1/s11ao to avoid dividing complex float c = 1000e-15; float z0 = 50; - //float z = 2 * M_PI * frequencies[i] * c * z0; + //float z = 2 * VNA_PI * frequencies[i] * c * z0; float z = 0.02; cal_data[ETERM_ED][i][0] += z; } @@ -1143,7 +1130,7 @@ eterm_calc_es(void) float c = 50e-15; //float c = 1.707e-12; float z0 = 50; - float z = 2 * M_PI * frequencies[i] * c * z0; + float z = 2 * VNA_PI * frequencies[i] * c * z0; float sq = 1 + z*z; float s11aor = (1 - z*z) / sq; float s11aoi = 2*z / sq; @@ -1279,7 +1266,7 @@ static void apply_error_term_at(int i) static void apply_edelay_at(int i) { - float w = 2 * M_PI * electrical_delay * frequencies[i] * 1E-12; + float w = 2 * VNA_PI * electrical_delay * frequencies[i] * 1E-12; float s = sin(w); float c = cos(w); float real = measured[0][i][0]; @@ -1296,35 +1283,20 @@ void cal_collect(int type) { ensure_edit_config(); - + int dst, src; switch (type) { - case CAL_LOAD: - cal_status |= CALSTAT_LOAD; - memcpy(cal_data[CAL_LOAD], measured[0], sizeof measured[0]); - break; - - case CAL_OPEN: - cal_status |= CALSTAT_OPEN; - cal_status &= ~(CALSTAT_ES|CALSTAT_APPLY); - memcpy(cal_data[CAL_OPEN], measured[0], sizeof measured[0]); - break; - - case CAL_SHORT: - cal_status |= CALSTAT_SHORT; - cal_status &= ~(CALSTAT_ER|CALSTAT_APPLY); - memcpy(cal_data[CAL_SHORT], measured[0], sizeof measured[0]); - break; - - case CAL_THRU: - cal_status |= CALSTAT_THRU; - memcpy(cal_data[CAL_THRU], measured[1], sizeof measured[0]); - break; - - case CAL_ISOLN: - cal_status |= CALSTAT_ISOLN; - memcpy(cal_data[CAL_ISOLN], measured[1], sizeof measured[0]); - break; + case CAL_LOAD: cal_status|= CALSTAT_LOAD; dst = CAL_LOAD; src = 0; break; + case CAL_OPEN: cal_status|= CALSTAT_OPEN; dst = CAL_OPEN; src = 0; cal_status&= ~(CALSTAT_ES|CALSTAT_APPLY); break; + case CAL_SHORT: cal_status|= CALSTAT_SHORT; dst = CAL_SHORT; src = 0; cal_status&= ~(CALSTAT_ER|CALSTAT_APPLY); break; + case CAL_THRU: cal_status|= CALSTAT_THRU; dst = CAL_THRU; src = 1; break; + case CAL_ISOLN: cal_status|= CALSTAT_ISOLN; dst = CAL_ISOLN; src = 1; break; + default: + return; } + // Run sweep for collect data + sweep(false); + // Copy calibration data + memcpy(cal_data[dst], measured[src], sizeof measured[0]); redraw_request |= REDRAW_CAL_STATUS; } @@ -1389,8 +1361,8 @@ cal_interpolate(int s) j = 0; for (; i < sweep_points; i++) { uint32_t f = frequencies[i]; - - for (; j < sweep_points-1; j++) { + if (f == 0) goto interpolate_finish; + for (; j < src->_sweep_points-1; j++) { if (src->_frequencies[j] <= f && f < src->_frequencies[j+1]) { // found f between freqs at j and j+1 float k1 = (float)(f - src->_frequencies[j]) @@ -1410,7 +1382,7 @@ cal_interpolate(int s) break; } } - if (j == sweep_points-1) + if (j == src->_sweep_points-1) break; } @@ -1418,11 +1390,11 @@ cal_interpolate(int s) for (; i < sweep_points; i++) { // fill cal_data at tail of src for (eterm = 0; eterm < 5; eterm++) { - cal_data[eterm][i][0] = src->_cal_data[eterm][sweep_points-1][0]; - cal_data[eterm][i][1] = src->_cal_data[eterm][sweep_points-1][1]; + cal_data[eterm][i][0] = src->_cal_data[eterm][src->_sweep_points-1][0]; + cal_data[eterm][i][1] = src->_cal_data[eterm][src->_sweep_points-1][1]; } } - +interpolate_finish: cal_status |= src->_cal_status | CALSTAT_APPLY | CALSTAT_INTERPOLATED; redraw_request |= REDRAW_CAL_STATUS; } @@ -1707,7 +1679,7 @@ VNA_SHELL_FUNCTION(cmd_marker) if (t < 0 || t >= MARKERS_MAX) goto usage; if (argc == 1) { - shell_printf("%d %d %d\r\n", t+1, markers[t].index, frequency); + shell_printf("%d %d %d\r\n", t+1, markers[t].index, markers[t].frequency); active_marker = t; // select active marker markers[t].enabled = TRUE; @@ -1764,7 +1736,7 @@ VNA_SHELL_FUNCTION(cmd_frequencies) (void)argv; for (i = 0; i < sweep_points; i++) { if (frequencies[i] != 0) - shell_printf("%d\r\n", frequencies[i]); + shell_printf("%u\r\n", frequencies[i]); } } @@ -1933,7 +1905,6 @@ VNA_SHELL_FUNCTION(cmd_stat) // shell_printf("awd: %d\r\n", awd_count); } - #ifndef VERSION #define VERSION "unknown" #endif @@ -1976,6 +1947,55 @@ VNA_SHELL_FUNCTION(cmd_info) } #endif +#ifdef ENABLE_COLOR_COMMAND +VNA_SHELL_FUNCTION(cmd_color) +{ + uint32_t color; + int i; + if (argc != 2) { + shell_printf("usage: color {id} {rgb24}\r\n"); + for (i=-3; i < TRACES_MAX; i++) { +#if 0 + switch(i){ + case -3: color = config.grid_color; break; + case -2: color = config.menu_normal_color; break; + case -1: color = config.menu_active_color; break; + default: color = config.trace_color[i];break; + } +#else + // WARNING!!! Dirty hack for size, depend from config struct + color = config.trace_color[i]; +#endif + color = ((color >> 3) & 0x001c00) | + ((color >> 5) & 0x0000f8) | + ((color << 16) & 0xf80000) | + ((color << 13) & 0x00e000); +// color = (color>>8)|(color<<8); +// color = ((color<<8)&0xF80000)|((color<<5)&0x00FC00)|((color<<3)&0x0000F8); + shell_printf(" %d: 0x%06x\r\n", i, color); + } + return; + } + i = my_atoi(argv[0]); + if (i < -3 && i >= TRACES_MAX) + return; + color = RGBHEX(my_atoui(argv[1])); +#if 0 + switch(i){ + case -3: config.grid_color = color; break; + case -2: config.menu_normal_color = color; break; + case -1: config.menu_active_color = color; break; + default: config.trace_color[i] = color;break; + } +#else + // WARNING!!! Dirty hack for size, depend from config struct + config.trace_color[i] = color; +#endif + // Redraw all + redraw_request|= REDRAW_AREA; +} +#endif + #ifdef ENABLE_THREADS_COMMAND #if CH_CFG_USE_REGISTRY == FALSE #error "Threads Requite enabled CH_CFG_USE_REGISTRY in chconf.h" @@ -2017,7 +2037,7 @@ typedef struct { } VNAShellCommand; #pragma pack(pop) -// Some commands can executed only if process thread not in main cycle +// Some commands can executed only in sweep thread, not in main cycle #define CMD_WAIT_MUTEX 1 static const VNAShellCommand commands[] = { @@ -2042,7 +2062,7 @@ static const VNAShellCommand commands[] = {"power" , cmd_power , 0}, {"sample" , cmd_sample , 0}, // {"gamma" , cmd_gamma , 0}, - {"scan" , cmd_scan , 0}, // Wait mutex hardcoded in cmd, need wait one sweep manually + {"scan" , cmd_scan , CMD_WAIT_MUTEX}, {"sweep" , cmd_sweep , 0}, {"test" , cmd_test , 0}, {"touchcal" , cmd_touchcal , CMD_WAIT_MUTEX}, @@ -2066,6 +2086,9 @@ static const VNAShellCommand commands[] = #ifdef ENABLE_INFO_COMMAND {"info" , cmd_info , 0}, #endif +#ifdef ENABLE_COLOR_COMMAND + {"color" , cmd_color , 0}, +#endif #ifdef ENABLE_THREADS_COMMAND {"threads" , cmd_threads , 0}, #endif @@ -2128,52 +2151,50 @@ static int VNAShell_readLine(char *line, int max_size){ return 0; } -// Macros for convert define value to string -#define STR1(x) #x -#define define_to_STR(x) STR1(x) // // Parse and run command line // static void VNAShell_executeLine(char *line){ // Parse and execute line - char *args[VNA_SHELL_MAX_ARGUMENTS + 1]; - int n = 0; char *lp = line, *ep; + shell_nargs = 0; while (*lp!=0){ // Skipping white space and tabs at string begin. while (*lp==' ' || *lp=='\t') lp++; // If an argument starts with a double quote then its delimiter is another quote, else delimiter is white space. ep = (*lp == '"') ? strpbrk(++lp, "\"") : strpbrk( lp, " \t"); // Store in args string - args[n++]=lp; + shell_args[shell_nargs++]=lp; // Stop, end of input string if ((lp = ep) == NULL) break; // Argument limits check - if (n > VNA_SHELL_MAX_ARGUMENTS) { + if (shell_nargs > VNA_SHELL_MAX_ARGUMENTS) { shell_printf("too many arguments, max "define_to_STR(VNA_SHELL_MAX_ARGUMENTS)""VNA_SHELL_NEWLINE_STR); return; } // Set zero at the end of string and continue check *lp++ = 0; } - if (n == 0) + if (shell_nargs == 0) return; // Execute line const VNAShellCommand *scp; for (scp = commands; scp->sc_name!=NULL;scp++) { - if (strcmp(scp->sc_name, args[0]) == 0) { - if (scp->flags&CMD_WAIT_MUTEX) { - chMtxLock(&mutex); - scp->sc_function(n-1, &args[1]); - chMtxUnlock(&mutex); + if (strcmp(scp->sc_name, shell_args[0]) == 0) { + if (scp->flags&CMD_WAIT_MUTEX){ + shell_function= scp->sc_function; + // Wait execute command in sweep thread + do{ + osalThreadSleepMilliseconds(100); + } while(shell_function); } else - scp->sc_function(n-1, &args[1]); + scp->sc_function(shell_nargs-1, &shell_args[1]); return; } } - shell_printf("%s?"VNA_SHELL_NEWLINE_STR, args[0]); + shell_printf("%s?"VNA_SHELL_NEWLINE_STR, shell_args[0]); } #ifdef VNA_SHELL_THREAD @@ -2209,6 +2230,10 @@ static const I2CConfig i2ccfg = { STM32_TIMINGR_PRESC(5U) | STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(3U) | STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U), + // 600kHz @ SYSCLK 48MHz, manually get values, x1.5 I2C speed, but need calc timings +// STM32_TIMINGR_PRESC(3U) | +// STM32_TIMINGR_SCLDEL(2U) | STM32_TIMINGR_SDADEL(2U) | +// STM32_TIMINGR_SCLH(4U) | STM32_TIMINGR_SCLL(4U), #else #error "Need Define STM32_I2C1SW and set correct TIMINGR settings" #endif @@ -2232,8 +2257,6 @@ int main(void) halInit(); chSysInit(); - chMtxObjectInit(&mutex); - //palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN); //palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(1) | PAL_STM32_OTYPE_OPENDRAIN); i2cStart(&I2CD1, &i2ccfg); diff --git a/nanovna.h b/nanovna.h index d5d14cc2..281fa264 100644 --- a/nanovna.h +++ b/nanovna.h @@ -25,8 +25,17 @@ /* * main.c */ -#define START_MIN 50000 -#define STOP_MAX 2700000000U + +// Minimum frequency set +#define START_MIN 50000 +// Maximum frequency set +#define STOP_MAX 2700000000U +// Frequency offset (sin_cos table in dsp.c generated for this offset, if change need create new table) +#define FREQUENCY_OFFSET 5000 +// Speed of light const +#define SPEED_OF_LIGHT 299792458 +// pi const +#define VNA_PI 3.14159265358979323846 #define POINTS_COUNT 101 extern float measured[2][POINTS_COUNT][2]; @@ -209,6 +218,10 @@ typedef struct trace { float refpos; } trace_t; +#define FREQ_MODE_START_STOP 0x0 +#define FREQ_MODE_CENTER_SPAN 0x1 +#define FREQ_MODE_DOTTED_GRID 0x2 + typedef struct config { int32_t magic; uint16_t dac_value; @@ -217,7 +230,7 @@ typedef struct config { uint16_t menu_active_color; uint16_t trace_color[TRACES_MAX]; int16_t touch_cal[4]; - int8_t reserved_1; + int8_t freq_mode; uint32_t harmonic_freq_threshold; uint16_t vbat_offset; uint8_t _reserved[22]; @@ -226,8 +239,6 @@ typedef struct config { extern config_t config; -//extern trace_t trace[TRACES_MAX]; - void set_trace_type(int t, int type); void set_trace_channel(int t, int channel); void set_trace_scale(int t, float scale); @@ -260,7 +271,7 @@ void redraw_frame(void); //void redraw_all(void); void request_to_draw_cells_behind_menu(void); void request_to_draw_cells_behind_numeric_input(void); -void redraw_marker(int marker, int update_info); +void redraw_marker(int marker); void plot_into_index(float measured[2][POINTS_COUNT][2]); void force_set_markmap(void); void draw_frequencies(void); @@ -283,6 +294,7 @@ int marker_search_right(int from); #define REDRAW_CAL_STATUS (1<<2) #define REDRAW_MARKER (1<<3) #define REDRAW_BATTERY (1<<4) +#define REDRAW_AREA (1<<5) extern volatile uint8_t redraw_request; /* @@ -396,13 +408,9 @@ extern properties_t current_props; #define velocity_factor current_props._velocity_factor #define marker_smith_format current_props._marker_smith_format -#define FREQ_IS_STARTSTOP() (frequency0 < frequency1) -#define FREQ_IS_CENTERSPAN() (frequency0 > frequency1) +#define FREQ_IS_STARTSTOP() (!(config.freq_mode&FREQ_MODE_CENTER_SPAN)) +#define FREQ_IS_CENTERSPAN() (config.freq_mode&FREQ_MODE_CENTER_SPAN) #define FREQ_IS_CW() (frequency0 == frequency1) -#define FREQ_START() (frequency0) -#define FREQ_STOP() (frequency1) -#define FREQ_CENTER() (frequency0/2 + frequency1/2) -#define FREQ_SPAN() (frequency0 - frequency1) int caldata_save(int id); int caldata_recall(int id); @@ -482,4 +490,7 @@ int plot_printf(char *str, int, const char *fmt, ...); // Speed profile definition #define START_PROFILE systime_t time = chVTGetSystemTimeX(); #define STOP_PROFILE {char string_buf[12];plot_printf(string_buf, sizeof string_buf, "T:%06d", chVTGetSystemTimeX() - time);ili9341_drawstringV(string_buf, 1, 60);} +// Macros for convert define value to string +#define STR1(x) #x +#define define_to_STR(x) STR1(x) /*EOF*/ diff --git a/plot.c b/plot.c index 5d712a61..a510b5b7 100644 --- a/plot.c +++ b/plot.c @@ -8,13 +8,17 @@ static void cell_draw_marker_info(int x0, int y0); static void draw_battery_status(void); -int16_t grid_offset; -int16_t grid_width; +static int16_t grid_offset; +static int16_t grid_width; int16_t area_width = AREA_WIDTH_NORMAL; int16_t area_height = AREA_HEIGHT_NORMAL; -// Depends from spi_buffer size, CELLWIDTH*CELLHEIGHT <= sizeof(spi_buffer) +// Cell render use spi buffer +typedef uint16_t pixel; +pixel *cell_buffer = (pixel *)spi_buffer; +// Cell size +// Depends from spi_buffer size, CELLWIDTH*CELLHEIGHT*sizeof(pixel) <= sizeof(spi_buffer) #define CELLWIDTH (64) #define CELLHEIGHT (32) // Check buffer size @@ -25,18 +29,27 @@ int16_t area_height = AREA_HEIGHT_NORMAL; // indicate dirty cells (not redraw if cell data not changed) #define MAX_MARKMAP_X ((320+CELLWIDTH-1)/CELLWIDTH) #define MAX_MARKMAP_Y ((240+CELLHEIGHT-1)/CELLHEIGHT) -uint16_t markmap[2][MAX_MARKMAP_Y]; -uint16_t current_mappage = 0; +// Define markmap mask size +#if MAX_MARKMAP_X <= 8 +typedef uint8_t map_t; +#elif MAX_MARKMAP_X <= 16 +typedef uint16_t map_t; +#elif MAX_MARKMAP_X <= 32 +typedef uint32_t map_t; +#endif + +map_t markmap[2][MAX_MARKMAP_Y]; +uint8_t current_mappage = 0; // Trace data cache, for faster redraw cells // CELL_X[16:31] x position // CELL_Y[ 0:15] y position -static uint32_t trace_index[TRACES_MAX][POINTS_COUNT]; +typedef uint32_t index_t; +static index_t trace_index[TRACES_MAX][POINTS_COUNT]; -#define INDEX(x, y) ((((uint32_t)x)<<16)|(((uint32_t)y))) +#define INDEX(x, y) ((((index_t)x)<<16)|(((index_t)y))) #define CELL_X(i) (int)(((i)>>16)) #define CELL_Y(i) (int)(((i)&0xFFFF)) -//#define CELL_P(i, x, y) (((((x)&0x03e0UL)<<22) | (((y)&0x03e0UL)<<17)) == ((i)&0xffc00000UL)) //#define floatToInt(v) ((int)(v)) static int @@ -412,7 +425,7 @@ logmag(const float *v) static float phase(const float *v) { - return 2 * atan2f(v[1], v[0]) / M_PI * 90; + return 2 * atan2f(v[1], v[0]) / VNA_PI * 90; } /* @@ -425,9 +438,9 @@ groupdelay(const float *v, const float *w, float deltaf) // atan(w)-atan(v) = atan((w-v)/(1+wv)) float r = w[0]*v[1] - w[1]*v[0]; float i = w[0]*v[0] + w[1]*v[1]; - return atan2f(r, i) / (2 * M_PI * deltaf); + return atan2f(r, i) / (2 * VNA_PI * deltaf); #else - return (atan2f(w[0], w[1]) - atan2f(v[0], v[1])) / (2 * M_PI * deltaf); + return (atan2f(w[0], w[1]) - atan2f(v[0], v[1])) / (2 * VNA_PI * deltaf); #endif } @@ -486,7 +499,7 @@ float groupdelay_from_array(int i, float array[POINTS_COUNT][2]) { int bottom = (i == 0) ? 0 : i - 1; - int top = (i == POINTS_COUNT-1) ? POINTS_COUNT-1 : i + 1; + int top = (i == sweep_points-1) ? sweep_points-1 : i + 1; float deltaf = frequencies[top] - frequencies[bottom]; return groupdelay(array[bottom], array[top], deltaf); } @@ -507,7 +520,7 @@ gamma2reactance(const float v[2]) return 2*v[1] * d; } -static uint32_t +static index_t trace_into_index(int t, int i, float array[POINTS_COUNT][2]) { int y, x; @@ -592,11 +605,11 @@ format_smith_value(char *buf, int len, const float coeff[2], uint32_t frequency) case MS_RLC: if (zi < 0){// Capacity prefix = 'F'; - value = -1 / (2 * M_PI * frequency * zi); + value = -1 / (2 * VNA_PI * frequency * zi); } else { prefix = 'H'; - value = zi / (2 * M_PI * frequency); + value = zi / (2 * VNA_PI * frequency); } plot_printf(buf, len, "%F"S_OHM" %F%c", zr, value, prefix); break; @@ -745,7 +758,6 @@ static float time_of_index(int idx) { } static float distance_of_index(int idx) { -#define SPEED_OF_LIGHT 299792458 float distance = ((float)idx * (float)SPEED_OF_LIGHT) / ( (float)(frequencies[1] - frequencies[0]) * (float)FFT_SIZE * 2.0); return distance * velocity_factor; } @@ -757,7 +769,7 @@ mark_map(int x, int y) markmap[current_mappage][y] |= 1<x1) SWAP(x0, x1); m0=m1; + int y0 = n0; int y1 = n1; if (y0>y1) SWAP(y0, y1); n0=n1; + for (; y0<=y1; y0++) + for(j=x0; j<=x1; j++) + map[y0]|= 1<=0 && y0=0 && x0= 0 && x0 < CELLWIDTH) - spi_buffer[y0*CELLWIDTH+x0] = (bits&0x80) ? c : DEFAULT_BG_COLOR; + cell_buffer[y0*CELLWIDTH+x0] = (bits&0x80) ? c : DEFAULT_BG_COLOR; x0++; bits<<=1; } @@ -1007,9 +1001,9 @@ draw_marker(int x, int y, int c, int ch) force_color = true; if (x0 >= 0 && x0 < CELLWIDTH && y0 >= 0 && y0 < CELLHEIGHT){ if (bits&0x80) - spi_buffer[y0*CELLWIDTH+x0] = c; + cell_buffer[y0*CELLWIDTH+x0] = c; else if (force_color) - spi_buffer[y0*CELLWIDTH+x0] = DEFAULT_BG_COLOR; + cell_buffer[y0*CELLWIDTH+x0] = DEFAULT_BG_COLOR; } x0++; bits<<=1; @@ -1026,7 +1020,7 @@ markmap_marker(int marker) for (t = 0; t < TRACES_MAX; t++) { if (!trace[t].enabled) continue; - uint32_t index = trace_index[t][markers[marker].index]; + index_t index = trace_index[t][markers[marker].index]; int x = CELL_X(index) - X_MARKER_OFFSET; int y = CELL_Y(index) - Y_MARKER_OFFSET; invalidateRect(x, y, x+MARKER_WIDTH-1, y+MARKER_HEIGHT-1); @@ -1048,7 +1042,7 @@ markmap_all_markers(void) void marker_position(int m, int t, int *x, int *y) { - uint32_t index = trace_index[t][markers[m].index]; + index_t index = trace_index[t][markers[m].index]; *x = CELL_X(index); *y = CELL_Y(index); } @@ -1068,8 +1062,8 @@ marker_search(void) return -1; int value = CELL_Y(trace_index[uistat.current_trace][0]); - for (i = 0; i < POINTS_COUNT; i++) { - uint32_t index = trace_index[uistat.current_trace][i]; + for (i = 0; i < sweep_points; i++) { + index_t index = trace_index[uistat.current_trace][i]; if ((*compare)(value, CELL_Y(index))) { value = CELL_Y(index); found = i; @@ -1096,14 +1090,14 @@ marker_search_left(int from) int value = CELL_Y(trace_index[uistat.current_trace][from]); for (i = from - 1; i >= 0; i--) { - uint32_t index = trace_index[uistat.current_trace][i]; + index_t index = trace_index[uistat.current_trace][i]; if ((*compare)(value, CELL_Y(index))) break; value = CELL_Y(index); } for (; i >= 0; i--) { - uint32_t index = trace_index[uistat.current_trace][i]; + index_t index = trace_index[uistat.current_trace][i]; if ((*compare)(CELL_Y(index), value)) { break; } @@ -1123,15 +1117,15 @@ marker_search_right(int from) return -1; int value = CELL_Y(trace_index[uistat.current_trace][from]); - for (i = from + 1; i < POINTS_COUNT; i++) { - uint32_t index = trace_index[uistat.current_trace][i]; + for (i = from + 1; i < sweep_points; i++) { + index_t index = trace_index[uistat.current_trace][i]; if ((*compare)(value, CELL_Y(index))) break; value = CELL_Y(index); } - for (; i < POINTS_COUNT; i++) { - uint32_t index = trace_index[uistat.current_trace][i]; + for (; i < sweep_points; i++) { + index_t index = trace_index[uistat.current_trace][i]; if ((*compare)(CELL_Y(index), value)) { break; } @@ -1144,7 +1138,7 @@ marker_search_right(int from) int search_nearest_index(int x, int y, int t) { - uint32_t *index = trace_index[t]; + index_t *index = trace_index[t]; int min_i = -1; int min_d = 1000; int i; @@ -1161,7 +1155,6 @@ search_nearest_index(int x, int y, int t) min_i = i; } } - return min_i; } @@ -1173,8 +1166,9 @@ plot_into_index(float measured[2][POINTS_COUNT][2]) if (!trace[t].enabled) continue; int ch = trace[t].channel; + index_t *index = trace_index[t]; for (i = 0; i < sweep_points; i++) - trace_index[t][i] = trace_into_index(t, i, measured[ch]); + index[i] = trace_into_index(t, i, measured[ch]); } #if 0 for (t = 0; t < TRACES_MAX; t++) @@ -1217,8 +1211,8 @@ draw_cell(int m, int n) #error "CELLWIDTH % 8 should be == 0 for speed, or need rewrite cell cleanup" #endif // Set DEFAULT_BG_COLOR for 8 pixels in one cycle - int count = h*CELLWIDTH / 8; - uint32_t *p = (uint32_t *)spi_buffer; + int count = h*CELLWIDTH / (16/sizeof(pixel)); + uint32_t *p = (uint32_t *)cell_buffer; while (count--) { p[0] = DEFAULT_BG_COLOR|(DEFAULT_BG_COLOR<<16); p[1] = DEFAULT_BG_COLOR|(DEFAULT_BG_COLOR<<16); @@ -1241,14 +1235,14 @@ draw_cell(int m, int n) for (x = 0; x < w; x++) { if (rectangular_grid_x(x+x0)){ for (y = 0; y < h; y++) - spi_buffer[y * CELLWIDTH + x] = c; + cell_buffer[y * CELLWIDTH + x] = c; } } for (y = 0; y < h; y++) { if (rectangular_grid_y(y+y0)){ for (x = 0; x < w; x++) if (x+x0 >= CELLOFFSETX && x+x0 <= WIDTH+CELLOFFSETX) - spi_buffer[y * CELLWIDTH + x] = c; + cell_buffer[y * CELLWIDTH + x] = c; } } } @@ -1257,22 +1251,22 @@ draw_cell(int m, int n) for (y = 0; y < h; y++) for (x = 0; x < w; x++) if (smith_grid(x+x0, y+y0)) - spi_buffer[y * CELLWIDTH + x] = c; + cell_buffer[y * CELLWIDTH + x] = c; } // Polar greed line (800 system ticks for all screen calls) else if(trace_type&(1<= 0 && (x+r) < CELLWIDTH && (0x80 & bits)) - spi_buffer[(y+c)*CELLWIDTH + (x+r)] = foreground_color; + cell_buffer[(y+c)*CELLWIDTH + (x+r)] = foreground_color; bits <<= 1; } } @@ -1580,9 +1579,9 @@ cell_draw_marker_info(int x0, int y0) cell_drawstring(S_SARROW, xpos, ypos); xpos += 5; - float light_speed_ps = 299792458e-12; //(m/ps) + float light_speed_ps = SPEED_OF_LIGHT*1e-12; //(m/ps) plot_printf(buf, sizeof buf, "Edelay %Fs %Fm", electrical_delay * 1e-12, - electrical_delay * light_speed_ps * velocity_factor); + electrical_delay * light_speed_ps * velocity_factor); cell_drawstring(buf, xpos, ypos); } } @@ -1593,18 +1592,18 @@ draw_frequencies(void) char buf1[32]; char buf2[32];buf2[0]=0; if ((domain_mode & DOMAIN_MODE) == DOMAIN_FREQ) { - if (FREQ_IS_STARTSTOP()) { - plot_printf(buf1, sizeof(buf1), " START %qHz", frequency0); - plot_printf(buf2, sizeof(buf2), " STOP %qHz", frequency1); - } else if (FREQ_IS_CENTERSPAN()) { - plot_printf(buf1, sizeof(buf1), " CENTER %qHz", FREQ_CENTER()); - plot_printf(buf2, sizeof(buf2), " SPAN %qHz", FREQ_SPAN()); - } else { - plot_printf(buf1, sizeof(buf1), " CW %qHz", frequency0); - } + if (FREQ_IS_CW()){ + plot_printf(buf1, sizeof(buf1), " CW %qHz", get_sweep_frequency(ST_CW)); + } else if (FREQ_IS_STARTSTOP()) { + plot_printf(buf1, sizeof(buf1), " START %qHz", get_sweep_frequency(ST_START)); + plot_printf(buf2, sizeof(buf2), " STOP %qHz", get_sweep_frequency(ST_STOP)); + } else if (FREQ_IS_CENTERSPAN()) { + plot_printf(buf1, sizeof(buf1), " CENTER %qHz", get_sweep_frequency(ST_CENTER)); + plot_printf(buf2, sizeof(buf2), " SPAN %qHz", get_sweep_frequency(ST_SPAN)); + } } else { - plot_printf(buf1, sizeof(buf1), " START 0s"); - plot_printf(buf2, sizeof(buf2), "STOP %Fs (%Fm)", time_of_index(POINTS_COUNT-1), distance_of_index(POINTS_COUNT-1)); + plot_printf(buf1, sizeof(buf1), " START 0s"); + plot_printf(buf2, sizeof(buf2), "STOP %Fs (%Fm)", time_of_index(sweep_points-1), distance_of_index(sweep_points-1)); } setForegroundColor(DEFAULT_FG_COLOR); setBackgroundColor(DEFAULT_BG_COLOR); @@ -1622,41 +1621,28 @@ draw_cal_status(void) { int x = 0; int y = 100; -#define YSTEP 8 + char c[3]; setForegroundColor(DEFAULT_FG_COLOR); setBackgroundColor(DEFAULT_BG_COLOR); - ili9341_fill(0, y, 10, 6*YSTEP, DEFAULT_BG_COLOR); + ili9341_fill(0, y, OFFSETX, 6*(FONT_GET_HEIGHT+1), DEFAULT_BG_COLOR); if (cal_status & CALSTAT_APPLY) { - char c[3] = "C0"; - c[1] += lastsaveid; - if (cal_status & CALSTAT_INTERPOLATED) - c[0] = 'c'; - else if (active_props == ¤t_props) - c[1] = '*'; + c[0] = cal_status & CALSTAT_INTERPOLATED ? 'c' : 'C'; + c[1] = active_props == ¤t_props ? '*' : '0' + lastsaveid; + c[2] = 0; ili9341_drawstring(c, x, y); - y += YSTEP; - } - - if (cal_status & CALSTAT_ED) { - ili9341_drawstring("D", x, y); - y += YSTEP; - } - if (cal_status & CALSTAT_ER) { - ili9341_drawstring("R", x, y); - y += YSTEP; - } - if (cal_status & CALSTAT_ES) { - ili9341_drawstring("S", x, y); - y += YSTEP; - } - if (cal_status & CALSTAT_ET) { - ili9341_drawstring("T", x, y); - y += YSTEP; - } - if (cal_status & CALSTAT_EX) { - ili9341_drawstring("X", x, y); - y += YSTEP; + y +=FONT_GET_HEIGHT+1; } + int i; + static const struct {char text, zero, mask;} calibration_text[]={ + {'D', 0, CALSTAT_ED}, + {'R', 0, CALSTAT_ER}, + {'S', 0, CALSTAT_ES}, + {'T', 0, CALSTAT_ET}, + {'X', 0, CALSTAT_EX} + }; + for (i = 0; i < 5; i++, y+=FONT_GET_HEIGHT+1) + if (cal_status & calibration_text[i].mask) + ili9341_drawstring(&calibration_text[i].text, x, y); } // Draw battery level diff --git a/si5351.c b/si5351.c index 92eeb8ae..aee7ba8c 100644 --- a/si5351.c +++ b/si5351.c @@ -36,8 +36,27 @@ // I2C address on bus (only 0x60 for Si5351A in 10-Pin MSOP) #define SI5351_I2C_ADDR 0x60 -static uint8_t current_band = 0; -static uint32_t current_freq = 0; +static uint8_t current_band = 0; +static uint32_t current_freq = 0; +static int32_t current_offset = FREQUENCY_OFFSET; + +// Minimum value is 2, freq change apply at next dsp measure, and need skip it +#define DELAY_NORMAL 2 +// Delay for bands (depend set band 1 more fast (can change before next dsp buffer ready, need wait additional interval) +#define DELAY_BAND_1 3 +#define DELAY_BAND_2 2 +// Band changes need set delay after reset PLL +#define DELAY_BANDCHANGE_1 3 +#define DELAY_BANDCHANGE_2 3 +// Delay after set new PLL values, and send reset (on band 1 unstable if less then 900, on 4000-5000 no amplitude spike on change) +#define DELAY_RESET_PLL 5000 + +uint32_t si5351_getFrequency(void) {return current_freq;} + +void si5351_set_frequency_offset(int32_t offset) { + current_offset = offset; + current_freq = 0; // reset freq, for +} static void si5351_bulk_write(const uint8_t *buf, int len) @@ -46,13 +65,26 @@ si5351_bulk_write(const uint8_t *buf, int len) (void)i2cMasterTransmitTimeout(&I2CD1, SI5351_I2C_ADDR, buf, len, NULL, 0, 1000); i2cReleaseBus(&I2CD1); } + #if 0 -static void si5351_bulk_read(uint8_t reg, uint8_t* buf, int len) +static bool si5351_bulk_read(uint8_t reg, uint8_t* buf, int len) { - int addr = SI5351_I2C_ADDR>>1; i2cAcquireBus(&I2CD1); - msg_t mr = i2cMasterTransmitTimeout(&I2CD1, addr, ®, 1, buf, len, 1000); + msg_t mr = i2cMasterTransmitTimeout(&I2CD1, SI5351_I2C_ADDR, ®, 1, buf, len, 1000); i2cReleaseBus(&I2CD1); + return mr == MSG_OK; +} + +static void si5351_wait_pll_lock(void) +{ + uint8_t status; + int count = 100; + do{ + status=0xFF; + si5351_bulk_read(0, &status, 1); + if ((status & 0x60) == 0) // PLLA and PLLB locked + return; + }while (--count); } #endif @@ -118,7 +150,7 @@ static void si5351_reset_pll(uint8_t mask) { // Writing a 1<<5 will reset PLLA, 1<<7 reset PLLB, this is a self clearing bits. // !!! Need delay before reset PLL for apply PLL freq changes before - chThdSleepMicroseconds(400); + chThdSleepMicroseconds(DELAY_RESET_PLL); si5351_write(SI5351_REG_177_PLL_RESET, mask | 0x0C); } @@ -335,14 +367,6 @@ static inline uint8_t si5351_getBand(uint32_t freq){ return 3; } -// Minimum value is 2, freq change apply at next dsp measure, and need skip it -#define DELAY_NORMAL 2 -// Additional delay for band 1 (remove unstable generation at begin) -#define DELAY_BAND_1 1 -// Band changes need additional delay after reset PLL -#define DELAY_BANDCHANGE_1 2 -#define DELAY_BANDCHANGE_2 2 - /* * Maximum supported frequency = FREQ_HARMONICS * 9U * configure output as follows: @@ -351,16 +375,21 @@ static inline uint8_t si5351_getBand(uint32_t freq){ * CLK2: fixed 8MHz */ int -si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength){ +si5351_set_frequency_with_offset(uint32_t freq, uint8_t drive_strength){ uint8_t band; int delay = DELAY_NORMAL; if (freq == current_freq) return delay; - uint32_t ofreq = freq + offset; + else if (current_freq > freq) // Reset band on sweep begin (if set range 150-600, fix error then 600 MHz band 2 or 3 go back) + current_band = 0; + current_freq = freq; + uint32_t ofreq = freq + current_offset; uint32_t mul = 1, omul = 1; uint32_t rdiv = SI5351_R_DIV_1; uint32_t fdiv; - current_freq = freq; + // Fix possible incorrect input + drive_strength&=SI5351_CLK_DRIVE_STRENGTH_MASK; + if (freq >= config.harmonic_freq_threshold * 7U) { mul = 9; omul = 11; @@ -383,7 +412,6 @@ si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_streng freq<<= 3; ofreq<<= 3; } - band = si5351_getBand(freq/mul); switch (band) { case 1: @@ -391,12 +419,13 @@ si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_streng if (current_band != 1){ si5351_setupPLL(SI5351_REG_PLL_A, PLL_N, 0, 1); si5351_set_frequency_fixedpll(2, XTALFREQ * PLL_N, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA|SI5351_CLK_PLL_SELECT_A); - delay+=DELAY_BANDCHANGE_1; + delay=DELAY_BANDCHANGE_1; } + else + delay=DELAY_BAND_1; // Calculate and set CH0 and CH1 divider si5351_set_frequency_fixedpll(0, (uint64_t)omul * XTALFREQ * PLL_N, ofreq, rdiv, drive_strength|SI5351_CLK_PLL_SELECT_A); si5351_set_frequency_fixedpll(1, (uint64_t) mul * XTALFREQ * PLL_N, freq, rdiv, drive_strength|SI5351_CLK_PLL_SELECT_A); - delay+=DELAY_BAND_1; break; case 2:// fdiv = 6 case 3:// fdiv = 4; @@ -405,8 +434,10 @@ si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_streng if (current_band != band){ si5351_setupMultisynth(0, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength|SI5351_CLK_PLL_SELECT_A); si5351_setupMultisynth(1, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength|SI5351_CLK_PLL_SELECT_B); - delay+=DELAY_BANDCHANGE_2; + delay=DELAY_BANDCHANGE_2; } + else + delay=DELAY_BAND_2; // Calculate and set CH0 and CH1 PLL freq si5351_setupPLL_freq(SI5351_REG_PLL_A, ofreq, fdiv, omul);// set PLLA freq = (ofreq/omul)*fdiv si5351_setupPLL_freq(SI5351_REG_PLL_B, freq, fdiv, mul);// set PLLB freq = ( freq/ mul)*fdiv @@ -414,7 +445,6 @@ si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_streng si5351_set_frequency_fixedpll(2, (uint64_t)freq*fdiv, CLK2_FREQUENCY*mul, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA|SI5351_CLK_PLL_SELECT_B); break; } - if (current_band != band) { si5351_reset_pll(SI5351_PLL_RESET_A|SI5351_PLL_RESET_B); current_band = band; diff --git a/si5351.h b/si5351.h index 6b5bdf5e..42a7d99e 100644 --- a/si5351.h +++ b/si5351.h @@ -72,4 +72,8 @@ void si5351_init(void); void si5351_disable_output(void); void si5351_enable_output(void); //void si5351_set_frequency(int channel, uint32_t freq, uint8_t drive_strength); -int si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength); + +void si5351_set_frequency_offset(int32_t offset); +int si5351_set_frequency_with_offset(uint32_t freq, uint8_t drive_strength); +uint32_t si5351_getFrequency(void); + diff --git a/ui.c b/ui.c index a2267da4..ae251265 100644 --- a/ui.c +++ b/ui.c @@ -767,7 +767,7 @@ menu_marker_search_cb(int item, uint8_t data) if (i != -1) markers[active_marker].index = i; draw_menu(); - redraw_marker(active_marker, TRUE); + redraw_marker(active_marker); select_lever_mode(LM_SEARCH); } @@ -776,7 +776,7 @@ menu_marker_smith_cb(int item, uint8_t data) { (void)item; marker_smith_format = data; - redraw_marker(active_marker, TRUE); + redraw_marker(active_marker); draw_menu(); } @@ -822,7 +822,7 @@ menu_marker_sel_cb(int item, uint8_t data) } else if (item == 5) { /* marker delta */ uistat.marker_delta = !uistat.marker_delta; } - redraw_marker(active_marker, TRUE); + redraw_marker(active_marker); draw_menu(); } @@ -1250,9 +1250,9 @@ draw_keypad(void) static void draw_numeric_area_frame(void) { - ili9341_fill(0, 240-NUM_INPUT_HEIGHT, 320, NUM_INPUT_HEIGHT, DEFAULT_MENU_COLOR); + ili9341_fill(0, 240-NUM_INPUT_HEIGHT, 320, NUM_INPUT_HEIGHT, config.menu_normal_color); setForegroundColor(DEFAULT_MENU_TEXT_COLOR); - setBackgroundColor(DEFAULT_MENU_COLOR); + setBackgroundColor(config.menu_normal_color); ili9341_drawstring(keypad_mode_label[keypad_mode], 10, 240-(FONT_GET_HEIGHT+NUM_INPUT_HEIGHT)/2); //ili9341_drawfont(KP_KEYPAD, 300, 216); } @@ -1267,7 +1267,7 @@ draw_numeric_input(const char *buf) for (i = 0, x = 64; i < 10 && buf[i]; i++, xsim<<=1) { uint16_t fg = DEFAULT_MENU_TEXT_COLOR; - uint16_t bg = DEFAULT_MENU_COLOR; + uint16_t bg = config.menu_normal_color; int c = buf[i]; if (c == '.') c = KP_PERIOD; @@ -1294,7 +1294,7 @@ draw_numeric_input(const char *buf) x += xsim&0x8000 ? NUM_FONT_GET_WIDTH+2+8 : NUM_FONT_GET_WIDTH+2; } // erase last - ili9341_fill(x, 240-NUM_INPUT_HEIGHT+4, NUM_FONT_GET_WIDTH+2+8, NUM_FONT_GET_WIDTH+2+8, DEFAULT_MENU_COLOR); + ili9341_fill(x, 240-NUM_INPUT_HEIGHT+4, NUM_FONT_GET_WIDTH+2+8, NUM_FONT_GET_WIDTH+2+8, config.menu_normal_color); } static int @@ -1639,18 +1639,18 @@ lever_move_marker(int status) if ((status & EVT_DOWN) && markers[active_marker].index > 0) { markers[active_marker].index--; markers[active_marker].frequency = frequencies[markers[active_marker].index]; - redraw_marker(active_marker, FALSE); + redraw_marker(active_marker); } - if ((status & EVT_UP) && markers[active_marker].index < 100) { + if ((status & EVT_UP) && markers[active_marker].index < sweep_points-1) { markers[active_marker].index++; markers[active_marker].frequency = frequencies[markers[active_marker].index]; - redraw_marker(active_marker, FALSE); + redraw_marker(active_marker); } } status = btn_wait_release(); } while (status != 0); if (active_marker >= 0) - redraw_marker(active_marker, TRUE); + redraw_marker(active_marker); } static void @@ -1664,7 +1664,7 @@ lever_search_marker(int status) i = marker_search_right(markers[active_marker].index); if (i != -1) markers[active_marker].index = i; - redraw_marker(active_marker, TRUE); + redraw_marker(active_marker); } } @@ -2067,7 +2067,7 @@ drag_marker(int t, int m) if (index >= 0) { markers[m].index = index; markers[m].frequency = frequencies[index]; - redraw_marker(m, TRUE); + redraw_marker(m); } } while(touch_check()!=EVT_TOUCH_RELEASED); } @@ -2097,7 +2097,7 @@ touch_pickup_marker(void) if (active_marker != m) { previous_marker = active_marker; active_marker = m; - redraw_marker(active_marker, TRUE); + redraw_marker(active_marker); } // select trace uistat.current_trace = t; @@ -2142,21 +2142,19 @@ void ui_process_touch(void) if (status == EVT_TOUCH_PRESSED || status == EVT_TOUCH_DOWN) { switch (ui_mode) { case UI_NORMAL: + // Try drag marker if (touch_pickup_marker()) break; + // Try select lever mode (top and bottom screen) if (touch_lever_mode_select()) { - draw_all(FALSE); touch_wait_release(); break; } - + // switch menu mode after release touch_wait_release(); - - // switch menu mode - selection = -1; + selection = -1; // hide keyboard mode selection ui_mode_menu(); break; - case UI_MENU: menu_apply_touch(); break;