Add support for LCD (ST7789)
This commit is contained in:
parent
66182d15bc
commit
adf405a230
|
@ -264,12 +264,12 @@ macro(nRF5x_setup)
|
||||||
|
|
||||||
list(APPEND SDK_SOURCE_FILES
|
list(APPEND SDK_SOURCE_FILES
|
||||||
"${NRF5_SDK_PATH}/components/libraries/gfx/nrf_gfx.c"
|
"${NRF5_SDK_PATH}/components/libraries/gfx/nrf_gfx.c"
|
||||||
"${NRF5_SDK_PATH}/integration/nrfx/legacy/nrf_drv_spi.c"
|
# "${NRF5_SDK_PATH}/integration/nrfx/legacy/nrf_drv_spi.c"
|
||||||
# "${NRF5_SDK_PATH}/modules/nrfx/drivers/src/nrfx_spi.c"
|
# "${NRF5_SDK_PATH}/modules/nrfx/drivers/src/nrfx_spim.c"
|
||||||
"${NRF5_SDK_PATH}/modules/nrfx/drivers/src/nrfx_spim.c"
|
# "${NRF5_SDK_PATH}/modules/nrfx/drivers/src/prs/nrfx_prs.c"
|
||||||
"${NRF5_SDK_PATH}/modules/nrfx/drivers/src/prs/nrfx_prs.c"
|
|
||||||
|
|
||||||
"${NRF5_SDK_PATH}/components/drivers_ext/st7735/st7735.c"
|
# "${NRF5_SDK_PATH}/components/drivers_ext/st7735/st7735.c"
|
||||||
|
"${NRF5_SDK_PATH}/external/thedotfactory_fonts/orkney24pts.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
#BLE S132
|
#BLE S132
|
||||||
|
|
|
@ -31,12 +31,16 @@ list(APPEND SOURCE_FILES
|
||||||
Logging/NrfLogger.cpp
|
Logging/NrfLogger.cpp
|
||||||
BlinkApp/BlinkApp.cpp
|
BlinkApp/BlinkApp.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
|
drivers/st7789.cpp
|
||||||
|
drivers/spi_master_fast.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(INCLUDE_FILES
|
set(INCLUDE_FILES
|
||||||
Logging/Logger.h
|
Logging/Logger.h
|
||||||
Logging/NrfLogger.h
|
Logging/NrfLogger.h
|
||||||
BlinkApp/BlinkApp.h
|
BlinkApp/BlinkApp.h
|
||||||
|
drivers/st7789.h
|
||||||
|
drivers/spi_master_fast.h
|
||||||
)
|
)
|
||||||
|
|
||||||
nRF5x_addExecutable(pinetime-app "${SOURCE_FILES}")
|
nRF5x_addExecutable(pinetime-app "${SOURCE_FILES}")
|
176
src/drivers/spi_master_fast.cpp
Normal file
176
src/drivers/spi_master_fast.cpp
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* The information contained herein is confidential property of Nordic
|
||||||
|
* Semiconductor ASA.Terms and conditions of usage are described in detail
|
||||||
|
* in NORDIC SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||||
|
*
|
||||||
|
* Licensees are granted free, non-transferable use of the information. NO
|
||||||
|
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||||
|
* the file.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "spi_master_fast.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "nrf_gpio.h"
|
||||||
|
#include "nrf_delay.h"
|
||||||
|
|
||||||
|
static SPI_config_t spi_config_table[2];
|
||||||
|
static NRF_SPI_Type *spi_base[2] = {NRF_SPI0, NRF_SPI1};
|
||||||
|
static NRF_SPI_Type *SPI;
|
||||||
|
|
||||||
|
uint32_t* spi_master_init(SPI_module_number_t spi_num, SPI_config_t *spi_config)
|
||||||
|
{
|
||||||
|
if(spi_num > 1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy(&spi_config_table[spi_num], spi_config, sizeof(SPI_config_t));
|
||||||
|
|
||||||
|
/* Configure GPIO pins used for pselsck, pselmosi, pselmiso and pselss for SPI0 */
|
||||||
|
nrf_gpio_cfg_output(spi_config->pin_SCK);
|
||||||
|
nrf_gpio_cfg_output(spi_config->pin_MOSI);
|
||||||
|
nrf_gpio_cfg_input(spi_config->pin_MISO, NRF_GPIO_PIN_NOPULL);
|
||||||
|
nrf_gpio_cfg_output(spi_config->pin_CSN);
|
||||||
|
|
||||||
|
/* Configure pins, frequency and mode */
|
||||||
|
spi_base[spi_num]->PSELSCK = spi_config->pin_SCK;
|
||||||
|
spi_base[spi_num]->PSELMOSI = spi_config->pin_MOSI;
|
||||||
|
spi_base[spi_num]->PSELMISO = spi_config->pin_MISO;
|
||||||
|
nrf_gpio_pin_set(spi_config->pin_CSN); /* disable Set slave select (inactive high) */
|
||||||
|
|
||||||
|
spi_base[spi_num]->FREQUENCY = (uint32_t)spi_config->frequency << 24;
|
||||||
|
|
||||||
|
spi_base[spi_num]->CONFIG = spi_config->config.SPI_cfg;
|
||||||
|
|
||||||
|
spi_base[spi_num]->EVENTS_READY = 0;
|
||||||
|
/* Enable */
|
||||||
|
spi_base[spi_num]->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos);
|
||||||
|
|
||||||
|
return (uint32_t *)spi_base[spi_num];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool spi_master_tx_rx(SPI_module_number_t spi_num, uint16_t transfer_size, const uint8_t *tx_data, uint8_t *rx_data)
|
||||||
|
{
|
||||||
|
volatile uint32_t *SPI_DATA_READY;
|
||||||
|
uint32_t tmp;
|
||||||
|
if(tx_data == 0 || rx_data == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPI = spi_base[spi_num];
|
||||||
|
SPI_DATA_READY = &SPI->EVENTS_READY;
|
||||||
|
/* enable slave (slave select active low) */
|
||||||
|
nrf_gpio_pin_clear(spi_config_table[spi_num].pin_CSN);
|
||||||
|
|
||||||
|
*SPI_DATA_READY = 0;
|
||||||
|
|
||||||
|
SPI->TXD = (uint32_t)*tx_data++;
|
||||||
|
tmp = (uint32_t)*tx_data++;
|
||||||
|
while(--transfer_size)
|
||||||
|
{
|
||||||
|
SPI->TXD = tmp;
|
||||||
|
tmp = (uint32_t)*tx_data++;
|
||||||
|
|
||||||
|
/* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
|
||||||
|
while (*SPI_DATA_READY == 0);
|
||||||
|
|
||||||
|
/* clear the event to be ready to receive next messages */
|
||||||
|
*SPI_DATA_READY = 0;
|
||||||
|
|
||||||
|
*rx_data++ = SPI->RXD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
|
||||||
|
while (*SPI_DATA_READY == 0);
|
||||||
|
|
||||||
|
*rx_data = SPI->RXD;
|
||||||
|
|
||||||
|
/* disable slave (slave select active low) */
|
||||||
|
nrf_gpio_pin_set(spi_config_table[spi_num].pin_CSN);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool spi_master_tx(SPI_module_number_t spi_num, uint16_t transfer_size, const uint8_t *tx_data)
|
||||||
|
{
|
||||||
|
volatile uint32_t dummyread;
|
||||||
|
|
||||||
|
if(tx_data == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPI = spi_base[spi_num];
|
||||||
|
|
||||||
|
/* enable slave (slave select active low) */
|
||||||
|
nrf_gpio_pin_clear(spi_config_table[spi_num].pin_CSN);
|
||||||
|
|
||||||
|
SPI->EVENTS_READY = 0;
|
||||||
|
|
||||||
|
SPI->TXD = (uint32_t)*tx_data++;
|
||||||
|
|
||||||
|
while(--transfer_size)
|
||||||
|
{
|
||||||
|
SPI->TXD = (uint32_t)*tx_data++;
|
||||||
|
|
||||||
|
/* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
|
||||||
|
while (SPI->EVENTS_READY == 0);
|
||||||
|
|
||||||
|
/* clear the event to be ready to receive next messages */
|
||||||
|
SPI->EVENTS_READY = 0;
|
||||||
|
|
||||||
|
dummyread = SPI->RXD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
|
||||||
|
while (SPI->EVENTS_READY == 0);
|
||||||
|
|
||||||
|
dummyread = SPI->RXD;
|
||||||
|
|
||||||
|
/* disable slave (slave select active low) */
|
||||||
|
nrf_gpio_pin_set(spi_config_table[spi_num].pin_CSN);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool spi_master_rx(SPI_module_number_t spi_num, uint16_t transfer_size, uint8_t *rx_data)
|
||||||
|
{
|
||||||
|
if(rx_data == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPI = spi_base[spi_num];
|
||||||
|
|
||||||
|
/* enable slave (slave select active low) */
|
||||||
|
nrf_gpio_pin_clear(spi_config_table[spi_num].pin_CSN);
|
||||||
|
|
||||||
|
SPI->EVENTS_READY = 0;
|
||||||
|
|
||||||
|
SPI->TXD = 0;
|
||||||
|
|
||||||
|
while(--transfer_size)
|
||||||
|
{
|
||||||
|
SPI->TXD = 0;
|
||||||
|
|
||||||
|
/* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
|
||||||
|
while (SPI->EVENTS_READY == 0);
|
||||||
|
|
||||||
|
/* clear the event to be ready to receive next messages */
|
||||||
|
SPI->EVENTS_READY = 0;
|
||||||
|
|
||||||
|
*rx_data++ = SPI->RXD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for the transaction complete or timeout (about 10ms - 20 ms) */
|
||||||
|
while (SPI->EVENTS_READY == 0);
|
||||||
|
|
||||||
|
*rx_data = SPI->RXD;
|
||||||
|
|
||||||
|
/* disable slave (slave select active low) */
|
||||||
|
nrf_gpio_pin_set(spi_config_table[spi_num].pin_CSN);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
147
src/drivers/spi_master_fast.h
Normal file
147
src/drivers/spi_master_fast.h
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* The information contained herein is confidential property of Nordic
|
||||||
|
* Semiconductor ASA.Terms and conditions of usage are described in detail
|
||||||
|
* in NORDIC SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
|
||||||
|
*
|
||||||
|
* Licensees are granted free, non-transferable use of the information. NO
|
||||||
|
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
|
||||||
|
* the file.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SPI_MASTER_FAST_H
|
||||||
|
#define __SPI_MASTER_FAST_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define SPI_FAST_DEFAULT_CONFIG {.pin_SCK = 1, .pin_MOSI = 2, .pin_MISO = 3, .pin_CSN = 4, \
|
||||||
|
.frequency = SPI_FREQ_1MBPS, .config.fields.mode = 0, .config.fields.bit_order = SPI_BITORDER_MSB_LSB}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SPI master operating frequency
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SPI_FREQ_125KBPS = 0x02, /*!< drive SClk with frequency 125Kbps */
|
||||||
|
SPI_FREQ_250KBPS = 0x04, /*!< drive SClk with frequency 250Kbps */
|
||||||
|
SPI_FREQ_500KBPS = 0x08, /*!< drive SClk with frequency 500Kbps */
|
||||||
|
SPI_FREQ_1MBPS = 0x10, /*!< drive SClk with frequency 1Mbps */
|
||||||
|
SPI_FREQ_2MBPS = 0x20, /*!< drive SClk with frequency 2Mbps */
|
||||||
|
SPI_FREQ_4MBPS = 0x40, /*!< drive SClk with frequency 4Mbps */
|
||||||
|
SPI_FREQ_8MBPS = 0x80 /*!< drive SClk with frequency 8Mbps */
|
||||||
|
} SPI_frequency_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SPI master module number
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SPI0 = 0, /*!< SPI module 0 */
|
||||||
|
SPI1 /*!< SPI module 1 */
|
||||||
|
} SPI_module_number_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SPI mode
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
//------------------------Clock polarity 0, Clock starts with level 0-------------------------------------------
|
||||||
|
SPI_MODE0 = 0, /*!< Sample data at rising edge of clock and shift serial data at falling edge */
|
||||||
|
SPI_MODE1, /*!< sample data at falling edge of clock and shift serial data at rising edge */
|
||||||
|
//------------------------Clock polarity 1, Clock starts with level 1-------------------------------------------
|
||||||
|
SPI_MODE2, /*!< sample data at falling edge of clock and shift serial data at rising edge */
|
||||||
|
SPI_MODE3 /*!< Sample data at rising edge of clock and shift serial data at falling edge */
|
||||||
|
} SPI_mode_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SPI master bit ordering
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SPI_BITORDER_MSB_LSB = 0, /*!< Most significant to least significant bit */
|
||||||
|
SPI_BITORDER_LSB_MSB /*!< Least significant to most significant bit */
|
||||||
|
} SPI_bit_order_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct containing all parameters necessary to configure the SPI interface
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint8_t SPI_cfg; /*!< Bit mode and bit order merged, as in the SPI CONFIG register */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t bit_order : 1; /*!< SPI master bit order */
|
||||||
|
uint8_t mode : 2; /*!< SPI master mode */
|
||||||
|
uint8_t : 5; /*!< Padding */
|
||||||
|
}fields;
|
||||||
|
}config;
|
||||||
|
uint8_t frequency; /*!< SPI master frequency */
|
||||||
|
uint8_t pin_SCK; /*!< SPI master SCK pin */
|
||||||
|
uint8_t pin_MOSI; /*!< SPI master MOSI pin */
|
||||||
|
uint8_t pin_MISO; /*!< SPI master MISO pin */
|
||||||
|
uint8_t pin_CSN; /*!< SPI master chip select pin */
|
||||||
|
} SPI_config_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes given SPI master with given configuration.
|
||||||
|
*
|
||||||
|
* After initializing the given SPI master with given configuration, this function also test if the
|
||||||
|
* SPI slave is responding with the configurations by transmitting few test bytes. If the slave did not
|
||||||
|
* respond then error is returned and contents of the rx_data are invalid.
|
||||||
|
*
|
||||||
|
* @param module_number SPI master number (SPIModuleNumber) to initialize.
|
||||||
|
* @param pointer to a struct of type @ref SPIConfig_t containing the SPI configuration parameters.
|
||||||
|
* @return
|
||||||
|
* @retval pointer to direct physical address of the requested SPI module if init was successful
|
||||||
|
* @retval 0, if either init failed or slave did not respond to the test transfer
|
||||||
|
*/
|
||||||
|
uint32_t* spi_master_init(SPI_module_number_t spi_num, SPI_config_t *spi_config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmit/receive data over SPI bus.
|
||||||
|
*
|
||||||
|
* @note Make sure at least transfer_size number of bytes is allocated in tx_data/rx_data.
|
||||||
|
*
|
||||||
|
* @param spi_num SPI master number (SPIModuleNumber)
|
||||||
|
* @param transfer_size number of bytes to transmit/receive over SPI master
|
||||||
|
* @param tx_data pointer to the data that needs to be transmitted
|
||||||
|
* @param rx_data pointer to the data that needs to be received
|
||||||
|
* @return
|
||||||
|
* @retval true if transmit/reveive of transfer_size were completed.
|
||||||
|
* @retval false if transmit/reveive of transfer_size were not complete and tx_data/rx_data points to invalid data.
|
||||||
|
*/
|
||||||
|
bool spi_master_tx_rx(SPI_module_number_t spi_num, uint16_t transfer_size, const uint8_t *tx_data, uint8_t *rx_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmit data over SPI bus.
|
||||||
|
*
|
||||||
|
* @note Make sure at least transfer_size number of bytes is allocated in tx_data.
|
||||||
|
*
|
||||||
|
* @param spi_num SPI master number (SPIModuleNumber)
|
||||||
|
* @param transfer_size number of bytes to transmit/receive over SPI master
|
||||||
|
* @param tx_data pointer to the data that needs to be transmitted
|
||||||
|
* @return
|
||||||
|
* @retval true if transmit/reveive of transfer_size were completed.
|
||||||
|
* @retval false if transmit/reveive of transfer_size were not complete and tx_data/rx_data points to invalid data.
|
||||||
|
*/
|
||||||
|
bool spi_master_tx(SPI_module_number_t spi_num, uint16_t transfer_size, const uint8_t *tx_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receive data over SPI bus.
|
||||||
|
*
|
||||||
|
* @note Make sure at least transfer_size number of bytes is allocated in rx_data.
|
||||||
|
*
|
||||||
|
* @param spi_num SPI master number (SPIModuleNumber)
|
||||||
|
* @param transfer_size number of bytes to transmit/receive over SPI master
|
||||||
|
* @param rx_data pointer to the data that needs to be received
|
||||||
|
* @return
|
||||||
|
* @retval true if transmit/reveive of transfer_size were completed.
|
||||||
|
* @retval false if transmit/reveive of transfer_size were not complete and tx_data/rx_data points to invalid data.
|
||||||
|
*/
|
||||||
|
bool spi_master_rx(SPI_module_number_t spi_num, uint16_t transfer_size, uint8_t *rx_data);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,5 +1,168 @@
|
||||||
//
|
#include <hal/nrf_gpio.h>
|
||||||
// Created by jf on 12/2/19.
|
#include <libraries/delay/nrf_delay.h>
|
||||||
//
|
|
||||||
|
|
||||||
#include "st7789.h"
|
#include "st7789.h"
|
||||||
|
#include "spi_master_fast.h"
|
||||||
|
|
||||||
|
using namespace Pinetime::Drivers;
|
||||||
|
|
||||||
|
ret_code_t st7789::Init() {
|
||||||
|
InitHw();
|
||||||
|
InitCommands();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ret_code_t st7789::InitHw() const {
|
||||||
|
nrf_gpio_cfg_output(ST7735_DC_PIN);
|
||||||
|
SPI_config_t spi_config;
|
||||||
|
|
||||||
|
spi_config.pin_SCK = ST7735_SCK_PIN;
|
||||||
|
spi_config.pin_MOSI = ST7735_MOSI_PIN;
|
||||||
|
spi_config.pin_MISO = ST7735_MISO_PIN;
|
||||||
|
spi_config.pin_CSN = ST7735_SS_PIN;
|
||||||
|
spi_config.frequency = SPI_FREQ_8MBPS;
|
||||||
|
spi_config.config.fields.mode = SPI_MODE3;
|
||||||
|
spi_config.config.fields.bit_order = SPI_BITORDER_MSB_LSB;
|
||||||
|
|
||||||
|
|
||||||
|
spi_master_init(SPI0, &spi_config);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::InitCommands() {
|
||||||
|
SoftwareReset();
|
||||||
|
SleepOut();
|
||||||
|
ColMod();
|
||||||
|
MemoryDataAccessControl();
|
||||||
|
ColumnAddressSet();
|
||||||
|
RowAddressSet();
|
||||||
|
DisplayInversionOn();
|
||||||
|
NormalModeOn();
|
||||||
|
DisplayOn();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::WriteCommand(uint8_t cmd) {
|
||||||
|
nrf_gpio_pin_clear(ST7735_DC_PIN);
|
||||||
|
WriteSpi(&cmd, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::WriteData(uint8_t data) {
|
||||||
|
nrf_gpio_pin_set(ST7735_DC_PIN);
|
||||||
|
WriteSpi(&data, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void st7789::WriteSpi(const uint8_t* data, size_t size) {
|
||||||
|
// APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, data, size, nullptr, 0));
|
||||||
|
spi_master_tx(SPI0, size, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::SoftwareReset() {
|
||||||
|
WriteCommand(static_cast<uint8_t>(Commands::SoftwareReset));
|
||||||
|
nrf_delay_ms(150);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::SleepOut() {
|
||||||
|
WriteCommand(static_cast<uint8_t>(Commands::SleepOut));
|
||||||
|
nrf_delay_ms(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::ColMod() {
|
||||||
|
WriteCommand(static_cast<uint8_t>(Commands::ColMod));
|
||||||
|
WriteData(0x55);
|
||||||
|
nrf_delay_ms(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::MemoryDataAccessControl() {
|
||||||
|
WriteCommand(static_cast<uint8_t>(Commands::MemoryDataAccessControl));
|
||||||
|
WriteData(0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::ColumnAddressSet() {
|
||||||
|
WriteCommand(static_cast<uint8_t>(Commands::ColumnAddressSet));
|
||||||
|
WriteData(0x00);
|
||||||
|
WriteData(0x00);
|
||||||
|
WriteData(Height >> 8);
|
||||||
|
WriteData(Height & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::RowAddressSet() {
|
||||||
|
WriteCommand(static_cast<uint8_t>(Commands::RowAddressSet));
|
||||||
|
WriteData(0x00);
|
||||||
|
WriteData(0x00);
|
||||||
|
WriteData(Width >> 8);
|
||||||
|
WriteData(Width & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::DisplayInversionOn() {
|
||||||
|
WriteCommand(static_cast<uint8_t>(Commands::DisplayInversionOn));
|
||||||
|
nrf_delay_ms(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::NormalModeOn() {
|
||||||
|
WriteCommand(static_cast<uint8_t>(Commands::NormalModeOn));
|
||||||
|
nrf_delay_ms(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::DisplayOn() {
|
||||||
|
WriteCommand(static_cast<uint8_t>(Commands::DisplayOn));
|
||||||
|
nrf_delay_ms(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::FillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color) {
|
||||||
|
// rudimentary clipping (drawChar w/big text requires this)
|
||||||
|
if((x >= Width) || (y >= Height)) return;
|
||||||
|
if((x + width - 1) >= Width) width = Width - x;
|
||||||
|
if((y + height - 1) >= Height) height = Height - y;
|
||||||
|
|
||||||
|
SetAddrWindow(0+x, ST7789_ROW_OFFSET+y, x+width-1, y+height-1);
|
||||||
|
|
||||||
|
uint8_t hi = color >> 8, lo = color;
|
||||||
|
uint32_t c = color + (color << 16);
|
||||||
|
|
||||||
|
nrf_gpio_pin_set(ST7735_DC_PIN);
|
||||||
|
for(y=height+ST7789_ROW_OFFSET; y>ST7789_ROW_OFFSET; y--) {
|
||||||
|
for(x=width; x>0; x--) {
|
||||||
|
WriteSpi(reinterpret_cast<const uint8_t *>(&c), 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
|
||||||
|
WriteCommand(static_cast<uint8_t>(Commands::ColumnAddressSet));
|
||||||
|
WriteData(x0 >> 8);
|
||||||
|
WriteData(x0 & 0xff);
|
||||||
|
WriteData(x1 >> 8);
|
||||||
|
WriteData(x1 & 0xff);
|
||||||
|
|
||||||
|
WriteCommand(static_cast<uint8_t>(Commands::RowAddressSet));
|
||||||
|
WriteData(y0>>8);
|
||||||
|
WriteData(y0 & 0xff);
|
||||||
|
WriteData(y1 >> 8);
|
||||||
|
WriteData(y1 & 0xff);
|
||||||
|
|
||||||
|
WriteToRam();
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::WriteToRam() {
|
||||||
|
WriteCommand(static_cast<uint8_t>(Commands::WriteToRam));
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::DisplayOff() {
|
||||||
|
WriteCommand(static_cast<uint8_t>(Commands::DisplayOff));
|
||||||
|
nrf_delay_ms(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::Uninit() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void st7789::DrawPixel(uint16_t x, uint16_t y, uint32_t color) {
|
||||||
|
if((x < 0) ||(x >= Width) || (y < 0) || (y >= Height)) return;
|
||||||
|
|
||||||
|
SetAddrWindow(x, y, x+1, y+1);
|
||||||
|
|
||||||
|
nrf_gpio_pin_set(ST7735_DC_PIN);
|
||||||
|
WriteSpi(reinterpret_cast<const uint8_t *>(&color), 2);
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,56 @@
|
||||||
//
|
#pragma once
|
||||||
// Created by jf on 12/2/19.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef PINETIME_ST7789_H
|
|
||||||
#define PINETIME_ST7789_H
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace Pinetime {
|
||||||
|
namespace Drivers {
|
||||||
class st7789 {
|
class st7789 {
|
||||||
|
public:
|
||||||
|
ret_code_t Init();
|
||||||
|
void Uninit();
|
||||||
|
void DrawPixel(uint16_t x, uint16_t y, uint32_t color);
|
||||||
|
void DrawRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t color);
|
||||||
|
void FillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ret_code_t InitHw() const;
|
||||||
|
void InitCommands();
|
||||||
|
|
||||||
|
void SoftwareReset();
|
||||||
|
void SleepOut();
|
||||||
|
void ColMod();
|
||||||
|
void MemoryDataAccessControl();
|
||||||
|
void DisplayInversionOn();
|
||||||
|
void NormalModeOn();
|
||||||
|
void WriteToRam();
|
||||||
|
void DisplayOn();
|
||||||
|
void DisplayOff();
|
||||||
|
|
||||||
|
void SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
|
||||||
|
|
||||||
|
void WriteCommand(uint8_t cmd);
|
||||||
|
void WriteSpi(const uint8_t* data, size_t size);
|
||||||
|
|
||||||
|
enum class Commands : uint8_t {
|
||||||
|
SoftwareReset = 0x01,
|
||||||
|
SleepOut = 0x11,
|
||||||
|
NormalModeOn = 0x13,
|
||||||
|
DisplayInversionOn = 0x21,
|
||||||
|
DisplayOff = 0x28,
|
||||||
|
DisplayOn = 0x29,
|
||||||
|
ColumnAddressSet = 0x2a,
|
||||||
|
RowAddressSet = 0x2b,
|
||||||
|
WriteToRam = 0x2c,
|
||||||
|
MemoryDataAccessControl = 036,
|
||||||
|
ColMod = 0x3a,
|
||||||
|
};
|
||||||
|
void WriteData(uint8_t data);
|
||||||
|
void ColumnAddressSet();
|
||||||
|
|
||||||
|
static constexpr uint16_t Width = 240;
|
||||||
|
static constexpr uint16_t Height = 240;
|
||||||
|
void RowAddressSet();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif //PINETIME_ST7789_H
|
|
||||||
|
|
94
src/main.cpp
94
src/main.cpp
|
@ -8,6 +8,7 @@
|
||||||
#include <libraries/timer/app_timer.h>
|
#include <libraries/timer/app_timer.h>
|
||||||
#include <libraries/gpiote/app_gpiote.h>
|
#include <libraries/gpiote/app_gpiote.h>
|
||||||
#include <libraries/gfx/nrf_lcd.h>
|
#include <libraries/gfx/nrf_lcd.h>
|
||||||
|
#include <drivers/st7789.h>
|
||||||
#include "nrf_gfx.h"
|
#include "nrf_gfx.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ Pinetime::Logging::DummyLogger logger;
|
||||||
|
|
||||||
Pinetime::Applications::BlinkApp blinkApp;
|
Pinetime::Applications::BlinkApp blinkApp;
|
||||||
TaskHandle_t systemThread;
|
TaskHandle_t systemThread;
|
||||||
|
Pinetime::Drivers::st7789 lcd;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void vApplicationIdleHook() {
|
void vApplicationIdleHook() {
|
||||||
|
@ -45,8 +46,48 @@ static void bsp_event_handler(bsp_event_t event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const nrf_lcd_t nrf_lcd_st7735;
|
ret_code_t lcd_init() {
|
||||||
static nrf_lcd_t const * p_lcd = &nrf_lcd_st7735;
|
lcd.Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_dummy() {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void lcd_pixel_draw(uint16_t x, uint16_t y, uint32_t color) {
|
||||||
|
lcd.DrawPixel(x, y, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void lcd_rectangle_draw(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t color) {
|
||||||
|
lcd.FillRectangle(x, y, width, height, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_rotation_set(nrf_lcd_rotation_t rotation) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcd_display_invert(bool invert) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static lcd_cb_t st7789_cb = {
|
||||||
|
.height = 240,
|
||||||
|
.width = 240
|
||||||
|
};
|
||||||
|
|
||||||
|
const nrf_lcd_t nrf_lcd_st7789 = {
|
||||||
|
.lcd_init = lcd_init,
|
||||||
|
.lcd_uninit = lcd_dummy,
|
||||||
|
.lcd_pixel_draw = lcd_pixel_draw,
|
||||||
|
.lcd_rect_draw = lcd_rectangle_draw,
|
||||||
|
.lcd_display = lcd_dummy,
|
||||||
|
.lcd_rotation_set = lcd_rotation_set,
|
||||||
|
.lcd_display_invert = lcd_display_invert,
|
||||||
|
.p_lcd_cb = &st7789_cb
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const FONT_INFO orkney_24ptFontInfo;
|
||||||
static void gfx_initialization(void)
|
static void gfx_initialization(void)
|
||||||
{
|
{
|
||||||
nrf_gpio_cfg_output(14);
|
nrf_gpio_cfg_output(14);
|
||||||
|
@ -56,24 +97,53 @@ static void gfx_initialization(void)
|
||||||
nrf_gpio_pin_set(22);
|
nrf_gpio_pin_set(22);
|
||||||
nrf_gpio_pin_set(23);
|
nrf_gpio_pin_set(23);
|
||||||
|
|
||||||
APP_ERROR_CHECK(nrf_gfx_init(p_lcd));
|
APP_ERROR_CHECK(nrf_gfx_init(&nrf_lcd_st7789));
|
||||||
nrf_gfx_rect_t rect;
|
nrf_gfx_rect_t rect;
|
||||||
rect.height = 10;
|
rect.height = 240;
|
||||||
rect.width = 10;
|
rect.width = 240;
|
||||||
rect.x = 10;
|
rect.x = 0;
|
||||||
rect.y = 10;
|
rect.y = 0;
|
||||||
nrf_gfx_rect_draw(p_lcd, &rect, 2, 0xffffffff, true);
|
nrf_gfx_rect_draw(&nrf_lcd_st7789, &rect, 2, 0xaaaaaaaa, true);
|
||||||
|
|
||||||
|
nrf_gfx_point_t point;
|
||||||
|
point.x = 10;
|
||||||
|
point.y = 10;
|
||||||
|
|
||||||
|
nrf_gfx_font_desc_t font;
|
||||||
|
font.charInfo = orkney_24ptFontInfo.charInfo;
|
||||||
|
font.data = orkney_24ptFontInfo.data;
|
||||||
|
font.endChar = orkney_24ptFontInfo.endChar;
|
||||||
|
font.height = orkney_24ptFontInfo.height;
|
||||||
|
font.spacePixels = orkney_24ptFontInfo.spacePixels;
|
||||||
|
font.startChar = orkney_24ptFontInfo.startChar;
|
||||||
|
|
||||||
|
|
||||||
|
nrf_gfx_print(&nrf_lcd_st7789,
|
||||||
|
&point,
|
||||||
|
0xffff,
|
||||||
|
"#Pinetime\nRocks!",
|
||||||
|
&font,
|
||||||
|
true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemTask(void *) {
|
void SystemTask(void *) {
|
||||||
APP_GPIOTE_INIT(2);
|
APP_GPIOTE_INIT(2);
|
||||||
app_timer_init();
|
app_timer_init();
|
||||||
|
|
||||||
bsp_board_init(BSP_INIT_LEDS|BSP_INIT_BUTTONS);
|
nrf_gpio_cfg_output(14);
|
||||||
bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
|
nrf_gpio_cfg_output(22);
|
||||||
|
nrf_gpio_cfg_output(23);
|
||||||
|
nrf_gpio_pin_clear(14);
|
||||||
|
nrf_gpio_pin_clear(22);
|
||||||
|
nrf_gpio_pin_clear(23);
|
||||||
|
|
||||||
gfx_initialization();
|
gfx_initialization();
|
||||||
|
// lcd.Init();
|
||||||
|
// lcd.FillRectangle(0,0,240,240,0xffaa);
|
||||||
|
// lcd.FillRectangle(10,10,50,50,0x011bb);
|
||||||
|
//
|
||||||
|
// lcd.FillRectangle(120,120,120,120,0x1212);
|
||||||
|
|
||||||
blinkApp.Start();
|
blinkApp.Start();
|
||||||
|
|
||||||
|
|
|
@ -4384,13 +4384,13 @@
|
||||||
// <e> NRFX_SPIM_ENABLED - nrfx_spim - SPIM peripheral driver
|
// <e> NRFX_SPIM_ENABLED - nrfx_spim - SPIM peripheral driver
|
||||||
//==========================================================
|
//==========================================================
|
||||||
#ifndef NRFX_SPIM_ENABLED
|
#ifndef NRFX_SPIM_ENABLED
|
||||||
#define NRFX_SPIM_ENABLED 1
|
#define NRFX_SPIM_ENABLED 0
|
||||||
#endif
|
#endif
|
||||||
// <q> NRFX_SPIM0_ENABLED - Enable SPIM0 instance
|
// <q> NRFX_SPIM0_ENABLED - Enable SPIM0 instance
|
||||||
|
|
||||||
|
|
||||||
#ifndef NRFX_SPIM0_ENABLED
|
#ifndef NRFX_SPIM0_ENABLED
|
||||||
#define NRFX_SPIM0_ENABLED 1
|
#define NRFX_SPIM0_ENABLED 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// <q> NRFX_SPIM1_ENABLED - Enable SPIM1 instance
|
// <q> NRFX_SPIM1_ENABLED - Enable SPIM1 instance
|
||||||
|
@ -4435,7 +4435,7 @@
|
||||||
// <e> NRFX_SPIM_CONFIG_LOG_ENABLED - Enables logging in the module.
|
// <e> NRFX_SPIM_CONFIG_LOG_ENABLED - Enables logging in the module.
|
||||||
//==========================================================
|
//==========================================================
|
||||||
#ifndef NRFX_SPIM_CONFIG_LOG_ENABLED
|
#ifndef NRFX_SPIM_CONFIG_LOG_ENABLED
|
||||||
#define NRFX_SPIM_CONFIG_LOG_ENABLED 1
|
#define NRFX_SPIM_CONFIG_LOG_ENABLED 0
|
||||||
#endif
|
#endif
|
||||||
// <o> NRFX_SPIM_CONFIG_LOG_LEVEL - Default Severity level
|
// <o> NRFX_SPIM_CONFIG_LOG_LEVEL - Default Severity level
|
||||||
|
|
||||||
|
@ -6456,7 +6456,7 @@
|
||||||
// <e> SPI_ENABLED - nrf_drv_spi - SPI/SPIM peripheral driver - legacy layer
|
// <e> SPI_ENABLED - nrf_drv_spi - SPI/SPIM peripheral driver - legacy layer
|
||||||
//==========================================================
|
//==========================================================
|
||||||
#ifndef SPI_ENABLED
|
#ifndef SPI_ENABLED
|
||||||
#define SPI_ENABLED 1
|
#define SPI_ENABLED 0
|
||||||
#endif
|
#endif
|
||||||
// <o> SPI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority
|
// <o> SPI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority
|
||||||
|
|
||||||
|
@ -6488,7 +6488,7 @@
|
||||||
// <e> SPI0_ENABLED - Enable SPI0 instance
|
// <e> SPI0_ENABLED - Enable SPI0 instance
|
||||||
//==========================================================
|
//==========================================================
|
||||||
#ifndef SPI0_ENABLED
|
#ifndef SPI0_ENABLED
|
||||||
#define SPI0_ENABLED 1
|
#define SPI0_ENABLED 0
|
||||||
#endif
|
#endif
|
||||||
// <q> SPI0_USE_EASY_DMA - Use EasyDMA
|
// <q> SPI0_USE_EASY_DMA - Use EasyDMA
|
||||||
|
|
||||||
|
@ -8146,7 +8146,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ST7735_ENABLED
|
#ifndef ST7735_ENABLED
|
||||||
#define ST7735_ENABLED 1
|
#define ST7735_ENABLED 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// <q> NRF_MEMOBJ_ENABLED - nrf_memobj - Linked memory allocator module
|
// <q> NRF_MEMOBJ_ENABLED - nrf_memobj - Linked memory allocator module
|
||||||
|
@ -9621,7 +9621,7 @@
|
||||||
// <e> SPI_CONFIG_LOG_ENABLED - Enables logging in the module.
|
// <e> SPI_CONFIG_LOG_ENABLED - Enables logging in the module.
|
||||||
//==========================================================
|
//==========================================================
|
||||||
#ifndef SPI_CONFIG_LOG_ENABLED
|
#ifndef SPI_CONFIG_LOG_ENABLED
|
||||||
#define SPI_CONFIG_LOG_ENABLED 1
|
#define SPI_CONFIG_LOG_ENABLED 0
|
||||||
#endif
|
#endif
|
||||||
// <o> SPI_CONFIG_LOG_LEVEL - Default Severity level
|
// <o> SPI_CONFIG_LOG_LEVEL - Default Severity level
|
||||||
|
|
||||||
|
@ -12967,6 +12967,10 @@
|
||||||
#define ST7735_SS_PIN 25
|
#define ST7735_SS_PIN 25
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef ST7789_ROW_OFFSET
|
||||||
|
#define ST7789_ROW_OFFSET 0
|
||||||
|
#endif
|
||||||
|
|
||||||
// <o> ST7735_IRQ_PRIORITY - Interrupt priority
|
// <o> ST7735_IRQ_PRIORITY - Interrupt priority
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue