From 6fbb6c8f70b2103fd88d8d9da3ce884a283b1bfd Mon Sep 17 00:00:00 2001 From: JF Date: Sat, 7 Dec 2019 17:11:50 +0100 Subject: Convert Spi and GFX to C++. diff --git a/cmake-nRF5x/CMake_nRF5x.cmake b/cmake-nRF5x/CMake_nRF5x.cmake index 29273e6..3157c5c 100755 --- a/cmake-nRF5x/CMake_nRF5x.cmake +++ b/cmake-nRF5x/CMake_nRF5x.cmake @@ -263,12 +263,6 @@ macro(nRF5x_setup) ) list(APPEND SDK_SOURCE_FILES - "${NRF5_SDK_PATH}/components/libraries/gfx/nrf_gfx.c" -# "${NRF5_SDK_PATH}/integration/nrfx/legacy/nrf_drv_spi.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}/components/drivers_ext/st7735/st7735.c" "${NRF5_SDK_PATH}/external/thedotfactory_fonts/orkney24pts.c" ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fb34595..d2ba5e2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,8 +33,9 @@ list(APPEND SOURCE_FILES DisplayApp/DisplayApp.cpp DisplayApp/lcdfont.c main.cpp - drivers/st7789.cpp - drivers/spi_master_fast.cpp + drivers/St7789.cpp + drivers/SpiMaster.cpp + Components/Gfx/Gfx.cpp ) set(INCLUDE_FILES @@ -43,8 +44,9 @@ set(INCLUDE_FILES BlinkApp/BlinkApp.h DisplayApp/DisplayApp.h DisplayApp/lcdfont.h - drivers/st7789.h - drivers/spi_master_fast.h + drivers/St7789.h + drivers/SpiMaster.h + Components/Gfx/Gfx.h ) nRF5x_addExecutable(pinetime-app "${SOURCE_FILES}") \ No newline at end of file diff --git a/src/Components/Gfx/Gfx.cpp b/src/Components/Gfx/Gfx.cpp new file mode 100644 index 0000000..e948c6c --- /dev/null +++ b/src/Components/Gfx/Gfx.cpp @@ -0,0 +1,76 @@ +#include +#include "Gfx.h" +#include "../../drivers/St7789.h" +using namespace Pinetime::Components; + +Gfx::Gfx(Pinetime::Drivers::St7789 &lcd) : lcd{lcd} { + lcd.Init(); +} + +void Gfx::ClearScreen() { + lcd.FillRectangle(0, 0, width, height, 0xffff); +} + +void Gfx::DrawString(uint8_t x, uint8_t y, uint16_t color, const char *text, const FONT_INFO *p_font, bool wrap) { + if (y > (height - p_font->height)) { + // Not enough space to write even single char. + return; + } + + uint8_t current_x = x; + uint8_t current_y = y; + + for (size_t i = 0; text[i] != '\0'; i++) { + if (text[i] == '\n') { + current_x = x; + current_y += p_font->height + p_font->height / 10; + } else { + DrawChar(p_font, (uint8_t) text[i], ¤t_x, current_y, color); + } + + uint8_t char_idx = text[i] - p_font->startChar; + uint16_t char_width = text[i] == ' ' ? (p_font->height / 2) : p_font->charInfo[char_idx].widthBits; + + if (current_x > (width - char_width)) { + if (wrap) { + current_x = x; + current_y += p_font->height + p_font->height / 10; + } else { + break; + } + + if (y > (height - p_font->height)) { + break; + } + } + } +} + +void Gfx::DrawChar(const FONT_INFO *font, uint8_t c, uint8_t *x, uint8_t y, uint16_t color) { + uint8_t char_idx = c - font->startChar; + uint16_t bytes_in_line = CEIL_DIV(font->charInfo[char_idx].widthBits, 8); + + if (c == ' ') { + *x += font->height / 2; + return; + } + + for (uint16_t i = 0; i < font->height; i++) { + for (uint16_t j = 0; j < bytes_in_line; j++) { + for (uint8_t k = 0; k < 8; k++) { + if ((1 << (7 - k)) & + font->data[font->charInfo[char_idx].offset + i * bytes_in_line + j]) { + pixel_draw(*x + j * 8 + k, y + i, color); + } + } + } + } + + *x += font->charInfo[char_idx].widthBits + font->spacePixels; +} + +void Gfx::pixel_draw(uint8_t x, uint8_t y, uint16_t color) { + lcd.DrawPixel(x, y, color); +} + + diff --git a/src/Components/Gfx/Gfx.h b/src/Components/Gfx/Gfx.h new file mode 100644 index 0000000..72293de --- /dev/null +++ b/src/Components/Gfx/Gfx.h @@ -0,0 +1,26 @@ +#pragma once +#include +#include + + +namespace Pinetime { + namespace Drivers { + class St7789; + } + namespace Components { + class Gfx { + public: + explicit Gfx(Drivers::St7789& lcd); + void ClearScreen(); + void DrawString(uint8_t x, uint8_t y, uint16_t color, const char* text, const FONT_INFO *p_font, bool wrap); + void DrawChar(const FONT_INFO *font, uint8_t c, uint8_t *x, uint8_t y, uint16_t color); + + + private: + Drivers::St7789& lcd; + const uint8_t width = 240; + const uint8_t height = 240; + void pixel_draw(uint8_t x, uint8_t y, uint16_t color); + }; + } +} diff --git a/src/DisplayApp/DisplayApp.cpp b/src/DisplayApp/DisplayApp.cpp index 36302a2..6dc31bc 100644 --- a/src/DisplayApp/DisplayApp.cpp +++ b/src/DisplayApp/DisplayApp.cpp @@ -3,57 +3,11 @@ #include #include #include -#include +#include +#include "Components/Gfx/Gfx.h" using namespace Pinetime::Applications; -Pinetime::Drivers::st7789 lcd; -ret_code_t lcd_init() { - return 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 -}; - -static 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; -//extern const uint_8 lCD_30ptBitmaps[]; -extern const FONT_INFO lCD_70ptFontInfo; -//extern const FONT_CHAR_INFO lCD_30ptDescriptors[]; - void DisplayApp::Start() { if (pdPASS != xTaskCreate(DisplayApp::Process, "DisplayApp", 256, this, 0, &taskHandle)) APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); @@ -62,123 +16,49 @@ void DisplayApp::Start() { void DisplayApp::Process(void *instance) { auto* app = static_cast(instance); - NRF_LOG_INFO("DisplayApp task started!"); - app->gfx_initialization(); - uint8_t hour = 0; - uint8_t minute = 1; + app->InitHw(); + while (1) { NRF_LOG_INFO("BlinkApp task running!"); - - nrf_gfx_rect_t rect; - rect.height = 74; - rect.width = 52; - rect.x = 7; - rect.y = 78; - nrf_gfx_rect_draw(&nrf_lcd_st7789, &rect, 2, 0x00000000, true); - - - - nrf_gfx_font_desc_t font; - font.charInfo = lCD_70ptFontInfo.charInfo; - font.data = lCD_70ptFontInfo.data; - font.endChar = lCD_70ptFontInfo.endChar; - font.height = lCD_70ptFontInfo.height; - font.spacePixels = lCD_70ptFontInfo.spacePixels; - font.startChar = lCD_70ptFontInfo.startChar; - - - char t[2]; - sprintf(t, "%1d", hour); - - nrf_gfx_point_t point; - point.x = 7; - point.y = 78; - nrf_gfx_print(&nrf_lcd_st7789, - &point, - 0xffff, - t, - &font, - true); - -// point.x = 61; -// point.y = 78; -// nrf_gfx_print(&nrf_lcd_st7789, -// &point, -// 0xffff, -// "2", -// &font, -// true); -// -// point.x = 115; -// point.y = 78; -// nrf_gfx_print(&nrf_lcd_st7789, -// &point, -// 0xffff, -// ":", -// &font, -// true); -// -// point.x = 127; -// point.y = 78; -// nrf_gfx_print(&nrf_lcd_st7789, -// &point, -// 0xffff, -// "3", -// &font, -// true); -// -// point.x = 181; -// point.y = 78; -// nrf_gfx_print(&nrf_lcd_st7789, -// &point, -// 0xffff, -// "4", -// &font, -// true); - - if(hour < 9) - hour++; - else hour = 0; vTaskDelay(1000); } } -void DisplayApp::gfx_initialization(void) -{ +void DisplayApp::InitHw() { nrf_gpio_cfg_output(14); nrf_gpio_cfg_output(22); nrf_gpio_cfg_output(23); nrf_gpio_pin_clear(14); - nrf_gpio_pin_set(22); - nrf_gpio_pin_set(23); + nrf_gpio_pin_clear(22); + nrf_gpio_pin_clear(23); + + Drivers::SpiMaster::Parameters params; + params.bitOrder = Drivers::SpiMaster::BitOrder::Msb_Lsb; + params.mode = Drivers::SpiMaster::Modes::Mode3; + params.Frequency = Drivers::SpiMaster::Frequencies::Freq8Mhz; + params.pinCSN = 25; + params.pinMISO = 4; + params.pinMOSI = 3; + params.pinSCK = 2; + spi.Init(Drivers::SpiMaster::SpiModule::SPI0, params); - APP_ERROR_CHECK(nrf_gfx_init(&nrf_lcd_st7789)); - nrf_gfx_rect_t rect; - rect.height = 240; - rect.width = 240; - rect.x = 0; - rect.y = 0; - nrf_gfx_rect_draw(&nrf_lcd_st7789, &rect, 2, 0x00000000, true); + lcd.reset(new Drivers::St7789(spi, 18)); + gfx.reset(new Components::Gfx(*lcd.get())); + gfx->ClearScreen(); - nrf_gfx_point_t point; - point.x = 7; - point.y = 78; + uint8_t x = 7; + gfx->DrawChar(&largeFont , '0', &x, 78, 0x0); - nrf_gfx_font_desc_t font; - font.charInfo = lCD_70ptFontInfo.charInfo; - font.data = lCD_70ptFontInfo.data; - font.endChar = lCD_70ptFontInfo.endChar; - font.height = lCD_70ptFontInfo.height; - font.spacePixels = lCD_70ptFontInfo.spacePixels; - font.startChar = lCD_70ptFontInfo.startChar; + x = 61; + gfx->DrawChar(&largeFont, '1', &x, 78, 0x0); + x = 115; + gfx->DrawChar(&largeFont, ':', &x, 78, 0x0); - nrf_gfx_print(&nrf_lcd_st7789, - &point, - 0xffff, - "20:45", - &font, - true); + x = 127; + gfx->DrawChar(&largeFont, '2', &x, 78, 0x0); + x = 181; + gfx->DrawChar(&largeFont, '3', &x, 78, 0x0); } diff --git a/src/DisplayApp/DisplayApp.h b/src/DisplayApp/DisplayApp.h index 08ecede..0fb6baf 100644 --- a/src/DisplayApp/DisplayApp.h +++ b/src/DisplayApp/DisplayApp.h @@ -1,18 +1,27 @@ #pragma once #include #include -#include +#include +#include +#include +#include + +extern const FONT_INFO lCD_70ptFontInfo; namespace Pinetime { namespace Applications { class DisplayApp { public: void Start(); + private: TaskHandle_t taskHandle; static void Process(void* instance); - void gfx_initialization(); - + void InitHw(); + Pinetime::Drivers::SpiMaster spi; + std::unique_ptr lcd; + std::unique_ptr gfx; + const FONT_INFO largeFont {lCD_70ptFontInfo.height, lCD_70ptFontInfo.startChar, lCD_70ptFontInfo.endChar, lCD_70ptFontInfo.spacePixels, lCD_70ptFontInfo.charInfo, lCD_70ptFontInfo.data}; }; } } diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp new file mode 100644 index 0000000..076c764 --- /dev/null +++ b/src/drivers/SpiMaster.cpp @@ -0,0 +1,88 @@ +#include +#include "SpiMaster.h" + +using namespace Pinetime::Drivers; + +bool SpiMaster::Init(const SpiMaster::SpiModule spi, const SpiMaster::Parameters ¶ms) { + /* Configure GPIO pins used for pselsck, pselmosi, pselmiso and pselss for SPI0 */ + nrf_gpio_cfg_output(params.pinSCK); + nrf_gpio_cfg_output(params.pinMOSI); + nrf_gpio_cfg_input(params.pinMISO, NRF_GPIO_PIN_NOPULL); + nrf_gpio_cfg_output(params.pinCSN); + pinCsn = params.pinCSN; + + switch(spi) { + case SpiModule::SPI0: spiBaseAddress = NRF_SPI0; break; + case SpiModule::SPI1: spiBaseAddress = NRF_SPI1; break; + default: return false; + } + + /* Configure pins, frequency and mode */ + spiBaseAddress->PSELSCK = params.pinSCK; + spiBaseAddress->PSELMOSI = params.pinMOSI; + spiBaseAddress->PSELMISO = params.pinMISO; + nrf_gpio_pin_set(pinCsn); /* disable Set slave select (inactive high) */ + + uint32_t frequency; + switch(params.Frequency) { + case Frequencies::Freq8Mhz: frequency = 0x80000000; break; + default: return false; + } + spiBaseAddress->FREQUENCY = frequency; + + uint32_t regConfig = 0; + switch(params.bitOrder) { + case BitOrder::Msb_Lsb: break; + case BitOrder::Lsb_Msb: regConfig = 1; + default: return false; + } + switch(params.mode) { + case Modes::Mode0: break; + case Modes::Mode1: regConfig |= (0x01 << 1); break; + case Modes::Mode2: regConfig |= (0x02 << 1); break; + case Modes::Mode3: regConfig |= (0x03 << 1); break; + default: return false; + } + + spiBaseAddress->CONFIG = regConfig; + spiBaseAddress->EVENTS_READY = 0; + spiBaseAddress->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos); + + return true; +} + +bool SpiMaster::Write(const uint8_t *data, size_t size) { + volatile uint32_t dummyread; + + if(data == nullptr) return false; + + /* enable slave (slave select active low) */ + nrf_gpio_pin_clear(pinCsn); + + spiBaseAddress->EVENTS_READY = 0; + + spiBaseAddress->TXD = (uint32_t)*data++; + + while(--size) + { + spiBaseAddress->TXD = (uint32_t)*data++; + + /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */ + while (spiBaseAddress->EVENTS_READY == 0); + + /* clear the event to be ready to receive next messages */ + spiBaseAddress->EVENTS_READY = 0; + + dummyread = spiBaseAddress->RXD; + } + + /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */ + while (spiBaseAddress->EVENTS_READY == 0); + + dummyread = spiBaseAddress->RXD; + + /* disable slave (slave select active low) */ + nrf_gpio_pin_set(pinCsn); + + return true; +} diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h new file mode 100644 index 0000000..10cab12 --- /dev/null +++ b/src/drivers/SpiMaster.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include + +namespace Pinetime { + namespace Drivers { + class SpiMaster { + public:; + enum class SpiModule : uint8_t {SPI0, SPI1}; + enum class BitOrder : uint8_t {Msb_Lsb, Lsb_Msb}; + enum class Modes : uint8_t {Mode0, Mode1, Mode2, Mode3}; + enum class Frequencies : uint8_t {Freq8Mhz}; + struct Parameters { + BitOrder bitOrder; + Modes mode; + Frequencies Frequency; + uint8_t pinSCK; + uint8_t pinMOSI; + uint8_t pinMISO; + uint8_t pinCSN; + }; + bool Init(const SpiModule spi, const Parameters& params); + + bool Write(const uint8_t* data, size_t size); + + private: + NRF_SPI_Type * spiBaseAddress; + uint8_t pinCsn; + }; + } +} diff --git a/src/drivers/St7789.cpp b/src/drivers/St7789.cpp new file mode 100644 index 0000000..dcc32fe --- /dev/null +++ b/src/drivers/St7789.cpp @@ -0,0 +1,149 @@ +#include +#include +#include "St7789.h" +#include "SpiMaster.h" + +using namespace Pinetime::Drivers; + +St7789::St7789(SpiMaster &spiMaster, uint8_t pinDataCommand) : spi{spiMaster}, pinDataCommand{pinDataCommand} { + +} + + +void St7789::Init() { + nrf_gpio_cfg_output(pinDataCommand); + SoftwareReset(); + SleepOut(); + ColMod(); + MemoryDataAccessControl(); + ColumnAddressSet(); + RowAddressSet(); + DisplayInversionOn(); + NormalModeOn(); + DisplayOn(); +} + +void St7789::WriteCommand(uint8_t cmd) { + nrf_gpio_pin_clear(pinDataCommand); + WriteSpi(&cmd, 1); +} + +void St7789::WriteData(uint8_t data) { + nrf_gpio_pin_set(pinDataCommand); + WriteSpi(&data, 1); +} + + +void St7789::WriteSpi(const uint8_t* data, size_t size) { + spi.Write(data, size); +} + +void St7789::SoftwareReset() { + WriteCommand(static_cast(Commands::SoftwareReset)); + nrf_delay_ms(150); +} + +void St7789::SleepOut() { + WriteCommand(static_cast(Commands::SleepOut)); + nrf_delay_ms(500); +} + +void St7789::ColMod() { + WriteCommand(static_cast(Commands::ColMod)); + WriteData(0x55); + nrf_delay_ms(10); +} + +void St7789::MemoryDataAccessControl() { + WriteCommand(static_cast(Commands::MemoryDataAccessControl)); + WriteData(0x00); +} + +void St7789::ColumnAddressSet() { + WriteCommand(static_cast(Commands::ColumnAddressSet)); + WriteData(0x00); + WriteData(0x00); + WriteData(Height >> 8); + WriteData(Height & 0xff); +} + +void St7789::RowAddressSet() { + WriteCommand(static_cast(Commands::RowAddressSet)); + WriteData(0x00); + WriteData(0x00); + WriteData(Width >> 8); + WriteData(Width & 0xff); +} + +void St7789::DisplayInversionOn() { + WriteCommand(static_cast(Commands::DisplayInversionOn)); + nrf_delay_ms(10); +} + +void St7789::NormalModeOn() { + WriteCommand(static_cast(Commands::NormalModeOn)); + nrf_delay_ms(10); +} + +void St7789::DisplayOn() { + WriteCommand(static_cast(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(pinDataCommand); + for(y=height+ST7789_ROW_OFFSET; y>ST7789_ROW_OFFSET; y--) { + for(x=width; x>0; x--) { + WriteSpi(reinterpret_cast(&c), 4); + } + } +} + +void St7789::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { + WriteCommand(static_cast(Commands::ColumnAddressSet)); + WriteData(x0 >> 8); + WriteData(x0 & 0xff); + WriteData(x1 >> 8); + WriteData(x1 & 0xff); + + WriteCommand(static_cast(Commands::RowAddressSet)); + WriteData(y0>>8); + WriteData(y0 & 0xff); + WriteData(y1 >> 8); + WriteData(y1 & 0xff); + + WriteToRam(); +} + +void St7789::WriteToRam() { + WriteCommand(static_cast(Commands::WriteToRam)); +} + +void St7789::DisplayOff() { + WriteCommand(static_cast(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(pinDataCommand); + WriteSpi(reinterpret_cast(&color), 2); +} + diff --git a/src/drivers/St7789.h b/src/drivers/St7789.h new file mode 100644 index 0000000..bd7f979 --- /dev/null +++ b/src/drivers/St7789.h @@ -0,0 +1,59 @@ +#pragma once +#include + +namespace Pinetime { + namespace Drivers { + class SpiMaster; + class St7789 { + public: + explicit St7789(SpiMaster& spiMaster, uint8_t pinDataCommand); + void Init(); + void Uninit(); + void DrawPixel(uint16_t x, uint16_t y, uint32_t color); + void FillRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color); + + + private: + SpiMaster& spi; + uint8_t pinDataCommand; + + 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(); + + }; + } +} + + diff --git a/src/drivers/spi_master_fast.cpp b/src/drivers/spi_master_fast.cpp deleted file mode 100644 index 7ef2b36..0000000 --- a/src/drivers/spi_master_fast.cpp +++ /dev/null @@ -1,176 +0,0 @@ - /* 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 -#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; -} diff --git a/src/drivers/spi_master_fast.h b/src/drivers/spi_master_fast.h deleted file mode 100644 index 3cda6ea..0000000 --- a/src/drivers/spi_master_fast.h +++ /dev/null @@ -1,147 +0,0 @@ - /* 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 -#include - -#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 diff --git a/src/drivers/st7789.cpp b/src/drivers/st7789.cpp deleted file mode 100644 index e88f110..0000000 --- a/src/drivers/st7789.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include -#include -#include "st7789.h" -#include "spi_master_fast.h" - -using namespace Pinetime::Drivers; - -ret_code_t st7789::Init() { - InitHw(); - InitCommands(); - return 0; -} - -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(Commands::SoftwareReset)); - nrf_delay_ms(150); -} - -void st7789::SleepOut() { - WriteCommand(static_cast(Commands::SleepOut)); - nrf_delay_ms(500); -} - -void st7789::ColMod() { - WriteCommand(static_cast(Commands::ColMod)); - WriteData(0x55); - nrf_delay_ms(10); -} - -void st7789::MemoryDataAccessControl() { - WriteCommand(static_cast(Commands::MemoryDataAccessControl)); - WriteData(0x00); -} - -void st7789::ColumnAddressSet() { - WriteCommand(static_cast(Commands::ColumnAddressSet)); - WriteData(0x00); - WriteData(0x00); - WriteData(Height >> 8); - WriteData(Height & 0xff); -} - -void st7789::RowAddressSet() { - WriteCommand(static_cast(Commands::RowAddressSet)); - WriteData(0x00); - WriteData(0x00); - WriteData(Width >> 8); - WriteData(Width & 0xff); -} - -void st7789::DisplayInversionOn() { - WriteCommand(static_cast(Commands::DisplayInversionOn)); - nrf_delay_ms(10); -} - -void st7789::NormalModeOn() { - WriteCommand(static_cast(Commands::NormalModeOn)); - nrf_delay_ms(10); -} - -void st7789::DisplayOn() { - WriteCommand(static_cast(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(&c), 4); - } - } -} - -void st7789::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { - WriteCommand(static_cast(Commands::ColumnAddressSet)); - WriteData(x0 >> 8); - WriteData(x0 & 0xff); - WriteData(x1 >> 8); - WriteData(x1 & 0xff); - - WriteCommand(static_cast(Commands::RowAddressSet)); - WriteData(y0>>8); - WriteData(y0 & 0xff); - WriteData(y1 >> 8); - WriteData(y1 & 0xff); - - WriteToRam(); -} - -void st7789::WriteToRam() { - WriteCommand(static_cast(Commands::WriteToRam)); -} - -void st7789::DisplayOff() { - WriteCommand(static_cast(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(&color), 2); -} diff --git a/src/drivers/st7789.h b/src/drivers/st7789.h deleted file mode 100644 index 6f744a1..0000000 --- a/src/drivers/st7789.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -namespace Pinetime { - namespace Drivers { - 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(); - - }; - } -} - - diff --git a/src/main.cpp b/src/main.cpp index c74eb71..b5588fa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,16 +2,11 @@ #include #include #include -#include #include #include #include #include -#include -#include #include -#include "nrf_gfx.h" - #if NRF_LOG_ENABLED #include "Logging/NrfLogger.h" @@ -24,7 +19,6 @@ Pinetime::Logging::DummyLogger logger; Pinetime::Applications::BlinkApp blinkApp; Pinetime::Applications::DisplayApp displayApp; TaskHandle_t systemThread; -//Pinetime::Drivers::st7789 lcd; extern "C" { void vApplicationIdleHook() { @@ -48,26 +42,10 @@ static void bsp_event_handler(bsp_event_t event) } } - - - - void SystemTask(void *) { APP_GPIOTE_INIT(2); app_timer_init(); - nrf_gpio_cfg_output(14); - 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); -// 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(); displayApp.Start(); @@ -76,8 +54,6 @@ void SystemTask(void *) { } } - - int main(void) { logger.Init(); nrf_drv_clock_init(); -- cgit v0.10.2